This is a nuuu style: gigadelic at prgmr with FreeBSD!

I spent a year with CentOS on gigadelic, my web server, and found myself itching for FreeBSD. This installment of my unintentional “How to install FreeBSD on things” series examines the steps necessary to get FreeBSD running comfortably in my Xen environment, a paravirtualized instance at prgmr.

Note: This information also lives on the Prgmr wiki and may be more up-to-date there.

FreeBSD has fairly complete Xen domU support, though it’s not as well-tested as NetBSD’s. Nor does the FreeBSD project distribute an easy domU distribution, like NetBSD’s netbsd-INSTALL_XEN3_DOMU.gz that’s runnable right from pvgrub, so the installation procedure is a tad involved.

You may either build your own copy of FreeBSD/Xen from an existing FreeBSD installation or download my prebuilt copy.

Some caveats:

  • Xen paravirtualization (PV), as used on prgmr, is supported only on FreeBSD i386, not amd64. FreeBSD amd64 supports only Xen HVM and is thus unusable in the prgmr environment.
  • Someone else’s binaries. Do you trust me?

Build Your Own Distribution

The operating system is built using the standard procedure, cross-compiling for i386 when necessary.

Patching

FreeBSD 9.0-RELEASE has a few outstanding issues on Xen, such as the inability to function with more than 768mb of provisioned memory and a panic when initializing SMP, even on vcpus=1 instances like mine. These two issues are fixed in 9-STABLE and will be rolled into 9.1-RELEASE later this year. I prefer to stick to releases when I can, though, so apply these two patches to your RELENG_9_0 source tree.

First, to fix the memory limitation. Taken from r228746.

  1. --- sys/i386/xen/pmap.c.orig 2011-11-10 23:20:22.000000000 -0500
  2. +++ sys/i386/xen/pmap.c 2012-03-27 12:36:06.553212765 -0400
  3. @@ -184,9 +184,6 @@
  4. #define PV_STAT(x) do { } while (0)
  5. #endif
  6. -#define pa_index(pa) ((pa) >> PDRSHIFT)
  7. -#define pa_to_pvh(pa) (&pv_table[pa_index(pa)])
  8. -
  9. /*
  10. * Get PDEs and PTEs for user/kernel address space
  11. */
  12. @@ -230,7 +227,6 @@
  13. * Data for the pv entry allocation mechanism
  14. */
  15. static int pv_entry_count = 0, pv_entry_max = 0, pv_entry_high_water = 0;
  16. -static struct md_page *pv_table;
  17. static int shpgperproc = PMAP_SHPGPERPROC;
  18. struct pv_chunk *pv_chunkbase; /* KVA block for pv_chunks */
  19. @@ -278,9 +274,6 @@
  20. static struct mtx PMAP2mutex;
  21. SYSCTL_NODE(_vm, OID_AUTO, pmap, CTLFLAG_RD, 0, "VM/pmap parameters");
  22. -static int pg_ps_enabled;
  23. -SYSCTL_INT(_vm_pmap, OID_AUTO, pg_ps_enabled, CTLFLAG_RDTUN, &pg_ps_enabled, 0,
  24. - "Are large page mappings enabled?");
  25. SYSCTL_INT(_vm_pmap, OID_AUTO, pv_entry_max, CTLFLAG_RD, &pv_entry_max, 0,
  26. "Max number of PV entries");
  27. @@ -636,24 +629,8 @@
  28. void
  29. pmap_init(void)
  30. {
  31. - vm_page_t mpte;
  32. - vm_size_t s;
  33. - int i, pv_npg;
  34. /*
  35. - * Initialize the vm page array entries for the kernel pmap's
  36. - * page table pages.
  37. - */
  38. - for (i = 0; i < nkpt; i++) {
  39. - mpte = PHYS_TO_VM_PAGE(xpmap_mtop(PTD[i + KPTDI] & PG_FRAME));
  40. - KASSERT(mpte >= vm_page_array &&
  41. - mpte < &vm_page_array[vm_page_array_size],
  42. - ("pmap_init: page table page is out of range"));
  43. - mpte->pindex = i + KPTDI;
  44. - mpte->phys_addr = xpmap_mtop(PTD[i + KPTDI] & PG_FRAME);
  45. - }
  46. -
  47. - /*
  48. * Initialize the address space (zone) for the pv entries. Set a
  49. * high water mark so that the system can recover from excessive
  50. * numbers of pv entries.
  51. @@ -664,26 +641,6 @@
  52. pv_entry_max = roundup(pv_entry_max, _NPCPV);
  53. pv_entry_high_water = 9 * (pv_entry_max / 10);
  54. - /*
  55. - * Are large page mappings enabled?
  56. - */
  57. - TUNABLE_INT_FETCH("vm.pmap.pg_ps_enabled", &pg_ps_enabled);
  58. -
  59. - /*
  60. - * Calculate the size of the pv head table for superpages.
  61. - */
  62. - for (i = 0; phys_avail[i + 1]; i += 2);
  63. - pv_npg = round_4mpage(phys_avail[(i - 2) + 1]) / NBPDR;
  64. -
  65. - /*
  66. - * Allocate memory for the pv head table for superpages.
  67. - */
  68. - s = (vm_size_t)(pv_npg * sizeof(struct md_page));
  69. - s = round_page(s);
  70. - pv_table = (struct md_page *)kmem_alloc(kernel_map, s);
  71. - for (i = 0; i < pv_npg; i++)
  72. - TAILQ_INIT(&pv_table[i].pv_list);
  73. -
  74. pv_maxchunks = MAX(pv_entry_max / _NPCPV, maxproc);
  75. pv_chunkbase = (struct pv_chunk *)kmem_alloc_nofault(kernel_map,
  76. PAGE_SIZE * pv_maxchunks);
  77. @@ -3452,21 +3409,15 @@
  78. }
  79. /*
  80. - * Returns TRUE if the given page is mapped individually or as part of
  81. - * a 4mpage. Otherwise, returns FALSE.
  82. + * Returns TRUE if the given page is mapped. Otherwise, returns FALSE.
  83. */
  84. boolean_t
  85. pmap_page_is_mapped(vm_page_t m)
  86. {
  87. - boolean_t rv;
  88. if ((m->oflags & VPO_UNMANAGED) != 0)
  89. return (FALSE);
  90. - vm_page_lock_queues();
  91. - rv = !TAILQ_EMPTY(&m->md.pv_list) ||
  92. - !TAILQ_EMPTY(&pa_to_pvh(VM_PAGE_TO_PHYS(m))->pv_list);
  93. - vm_page_unlock_queues();
  94. - return (rv);
  95. + return (!TAILQ_EMPTY(&m->md.pv_list));
  96. }
  97. /*

And second, to bypass the SMP panic by limiting MAXCPU to 1. It may be worth building 9-STABLE instead if you require SMP support.

  1. --- sys/i386/include/param.h.orig 2012-03-27 16:15:06.767507025 -0400
  2. +++ sys/i386/include/param.h 2012-03-27 15:46:33.525462762 -0400
  3. @@ -69,7 +69,7 @@
  4. #if defined(SMP) || defined(KLD_MODULE)
  5. #ifndef MAXCPU
  6. -#define MAXCPU 32
  7. +#define MAXCPU 1
  8. #endif
  9. #else
  10. #define MAXCPU 1

Optionally, patch xen/clock.c to silence annoying repeated console-spamming clock nudge messages unless the system is booted verbosely. Seen in kern/155353.

  1. --- sys/i386/xen/clock.c.orig 2012-03-15 12:33:13.887459073 -0400
  2. +++ sys/i386/xen/clock.c 2012-03-15 12:35:03.189146788 -0400
  3. @@ -349,7 +349,8 @@
  4. if (shadow_tv_version != HYPERVISOR_shared_info->wc_version &&
  5. !independent_wallclock) {
  6. - printf("[XEN] hypervisor wallclock nudged; nudging TOD.\n");
  7. + if(bootverbose)
  8. + printf("[XEN] hypervisor wallclock nudged; nudging TOD.\n");
  9. update_wallclock();
  10. add_uptime_to_wallclock();
  11. tc_setclock(&shadow_tv);

Kernel Configuration

The stock XEN kernel config file should boot with no trouble. You’ll probably want to customize it a bit, though, to enable features like PF/ALTQ and to disable the system-slowing kernel debugging features, especially witness. Disable debugging with caution. You may want to build a XEN kernel first to ensure it boots and to diagnose why if it doesn’t.

  1. --- sys/i386/conf/XEN 2011-11-10 23:20:22.000000000 -0500
  2. +++ sys/i386/conf/XEN-COOLTRAINER 2012-04-03 16:04:41.674814536 -0400
  3. @@ -44,16 +44,6 @@
  4. options KBD_INSTALL_CDEV # install a CDEV entry in /dev
  5. options AUDIT # Security event auditing
  6. -# Debugging for use in -current
  7. -options KDB # Enable kernel debugger support.
  8. -options DDB # Support DDB.
  9. -options GDB # Support remote GDB.
  10. -options DEADLKRES # Enable the deadlock resolver
  11. -options INVARIANTS # Enable calls of extra sanity checking
  12. -options INVARIANT_SUPPORT # Extra sanity checks of internal structures, required by INVARIANTS
  13. -options WITNESS # Enable checks to detect deadlocks and cycles
  14. -options WITNESS_SKIPSPIN # Don't run witness on spinlocks for speed
  15. -
  16. options PAE
  17. nooption NATIVE
  18. option XEN
  19. @@ -88,3 +78,16 @@
  20. # Note that 'bpf' is required for DHCP.
  21. device bpf # Berkeley packet filter
  22. +# Enable PF
  23. +device pf
  24. +device pflog
  25. +device pfsync
  26. +
  27. +# Enable ALTQ (QoS)
  28. +options ALTQ
  29. +options ALTQ_CBQ # Class Bases Queuing (CBQ)
  30. +options ALTQ_RED # Random Early Detection (RED)
  31. +options ALTQ_RIO # RED In/Out
  32. +options ALTQ_HFSC # Hierarchical Packet Scheduler (HFSC)
  33. +options ALTQ_PRIQ # Priority Queuing (PRIQ)
  34. +options ALTQ_NOPCC # Required for SMP build

Build

You’re ready to build your i386 world and kernel. Use the TARGET and TARGET_ARCH environment variables to cross-compile for i386 if necessary, such as on my amd64 build host. Specify either the stock XEN kernel configuration or the name of any custom configuration you create.

  1. make buildworld TARGET=i386
  2. make buildkernel TARGET_ARCH=i386 TARGET=i386 KERNCONF=XEN-COOLTRAINER

Install

Create a directory to serve as the temporary home of your OS distribution, set DESTDIR to its path, and install.

  1. mkdir /root/xenworld
  2. export DESTDIR=/root/xenworld
  3. make installworld TARGET=i386
  4. make installkernel KERNCONF=XEN-COOLTRAINER TARGET_ARCH=i386 TARGET=i386
  5. make distribution TARGET=i386

Configure

Set the mount options in fstab for what will be our root filesystem.

  1. echo "/dev/xbd0s2 / ufs rw 1 1" > $DESTDIR/etc/fstab

Remove the default virtual terminals from /etc/ttys. They don’t exist in the Xen environment and will throw errors into your console at boot if included. Then, add a line for the Xen console device so we can access the system via our out-of-band console.

  1. sed -i '' '/^ttyv/d' $DESTDIR/etc/ttys
  2. echo "xc0 "/usr/libexec/getty Pc" vt100 on secure" >> $DESTDIR/etc/ttys

Make any other changes you wish to include, create a tarball of the Xen world, and copy the kernel ELF out of DESTDIR for later use.

  1. cp $DESTDIR/boot/kernel/kernel /root/kernel
  2. cd $DESTDIR && tar zcvf /root/xenworld.tar.gz .

Partitioning

If you’re converting an existing Prgmr instance to FreeBSD, double-check your backups and make sure it holds nothing you’d be mad at yourself for losing.

Reboot your instance to the CentOS rescue environment via the out-of-band console, then blow away your disk with fdisk. Create a 512MiB Linux partition, then dedicate the rest of the disk to FreeBSD, hexadecimal partition type a5.

My properly-partitioned 25GB disk on gigadelic looks like this:

  1. [root@gigadelic ~]# fdisk /dev/xvda
  2. Disk /dev/xvda: 25.7 GB, 25769803776 bytes
  3. 255 heads, 63 sectors/track, 3133 cylinders
  4. Units = cylinders of 16065 * 512 = 8225280 bytes
  5. Device Boot Start End Blocks Id System
  6. /dev/xvda1 1 63 506016 83 Linux
  7. /dev/xvda2 64 3133 24659775 a5 FreeBSD

Format your Linux partition as ext2, a nice universally-mountable default, then mount it and create some needed directories.

  1. mkfs.ext2 /dev/xvda1
  2. mount /dev/xvda1 /mnt && cd /mnt
  3. mkdir -p boot/grub

Transfer your kernel ELF and world tarball to the root of the ext partition. These two files will consume approximately 5MiB and 150MiB, respectively. I hosted the two files using www/woof from my build machine.

Host
  1. [root@emi#src] woof -i 172.16.0.40 /root/xenworld/boot/kernel/kernel
  2. Now serving on http://172.16.0.40:8080/
  3. gigadelic.cooltrainer.org - - [05/Apr/2012 10:45:06] "GET /kernel HTTP/1.0" 200 -
Xen
  1. wget http://emi.aloe.cooltrainer.org:8080/kernel
  2. wget http://emi.aloe.cooltrainer.org:8080/xenworld.tar.gz

Alternatively, download my pre-built world and kernel.

  1. wget http://prgmr.com/~nb/images/beta/kernel-XEN-COOLTRAINER
  2. wget http://prgmr.com/~nb/images/beta/xenworld.tar.gz

Move your kernel of choice to the /mnt/boot directory with filename kernel.

  1. mv kernel-XEN-COOLTRAINER boot/kernel

UFS via NetBSD

Reboot your instance once more, this time to the included NetBSD installer. If your dom0 doesn’t include NetBSD, check the directions for fetching the installer in the NetBSD how-to wiki article.

Drop to a shell when given the option. Double-check your partition layout with NetBSD’s fdisk. Your disk device will be /dev/xbd0.

  1. fdisk xbd0
  1. Disk: /dev/rxbd0d
  2. NetBSD disklabel disk geometry:
  3. cylinders: 24576, heads: 1, sectors/track: 2048 (2048 sectors/cylinder)
  4. total sectors: 50331648
  5. BIOS disk geometry:
  6. cylinders: 1024, heads: 255, sectors/track: 63 (16065 sectors/cylinder)
  7. total sectors: 50331648
  8. Partition table:
  9. 0: Linux native (sysid 131)
  10. start 63, size 1012032 (494 MB, Cyls 0-62)
  11. PBR is not bootable: All bytes are identical (0x00)
  12. 1: FreeBSD or 386BSD or old NetBSD (sysid 165)
  13. start 1012095, size 49319550 (24082 MB, Cyls 63-3132)
  14. PBR is not bootable: Bad magic number (0x5da0)
  15. 2: <UNUSED>
  16. 3: <UNUSED>
  17. No active partition.
  18. Drive serial number: 331975 (0x000510c7)

The FreeBSD partition you created in Linux’s fdisk will show up as slice f and the ext partition as slice e of xbd0, as visualized here in the partitioning step of NetBSD’s guided installer.

  1. Start MB End MB Size MB FS type Newfs Mount Mount point
  2. --------- --------- --------- ---------- ----- ----- -----------
  3. a: 0 0 0 unused
  4. b: 0 0 0 unused
  5. c: 0 24575 24576 NetBSD partition
  6. d: 0 24575 24576 Whole disk
  7. e: 0 493 494 Linux Ext2
  8. >f: 494 24574 24081 FFSv1 Yes Yes /
  9. g: 0 0 0 unused
  10. h: Show all unused partitions
  11. i: Change input units (sectors/cylinders/MB)
  12. x: Partition sizes ok

Create a new FFSv2 filesystem on slice f.

  1. newfs -O 2 /dev/rxbd0f

Create mountpoints for both partitions, mount them, and extract your FreeBSD world tarball.

  1. mkdir -p /mnt/{boot,world}
  2. mount -t ext2fs /dev/xbd0e /mnt/boot
  3. mount /dev/xbd0f /mnt/world
  4. tar zxvf /mnt/boot/xenworld.tar.gz -C /mnt/world

Bootloader Configuration

While still in NetBSD, create a text file at /mnt/boot/boot/grub/menu.lst. pvgrub will expect the user bootloader configuration in (hd0,0)/boot/grub/menu.lst. (hd0,0) is your ext2 partition in this case.

boot/grub/menu.lst
  1. timeout 5
  2. title FreeBSD
  3. root (hd0,0)
  4. kernel /boot/kernel vfs.root.mountfrom=ufs:xbd0s2,machdep.idle_mwait=0,kern.hz=100
  5. title FreeBSD Verbose
  6. root (hd0,0)
  7. kernel /boot/kernel vfs.root.mountfrom=ufs:xbd0s2,machdep.idle_mwait=0,kern.hz=100,bootverbose=1

The kernel lines’ arguments instruct the kernel to root from /dev/xbd0s2, as seen earlier in fstab, to avoid a panic seen in kern/152228, and to tick the system clock at 100hz. kern.hz should be detected automatically, but specifying it here won’t hurt. The second pvgrub entry is identical but boots verbosely.

Once that’s in place, shut down the instance and make sure, through the admininstation console, that you’re using the i386 pvgrub. amd64 pvgrub cannot load our i386 kernel ELF. Option #6 in the console allows you to swap bootloaders.

  1. 6. swap i386/amd64 bootloaders (pvgrub) currently i386

Finally, start your instance and watch through the out-of-band console as pvgrub loads your user configuration and eventually the FreeBSD kernel!

First Boot Maintenance

Booted successfully? Awesome. There are just a few things to take care of before you can settle in to FreeBSD.

First, use mtree to repair directory and file permissions and flags mangled by NetBSD’s tar.

  1. mtree -U -p / -f /etc/mtree/BSD.root.dist
  2. mtree -U -p /usr -f /etc/mtree/BSD.usr.dist
  3. mtree -U -p /usr/local -f /etc/mtree/BSD.local.dist
  4. mtree -U -p /usr/include -f /etc/mtree/BSD.include.dist
  5. mtree -U -p /var -f /etc/mtree/BSD.var.dist

Enable the Blowfish hash function in auth.conf instead of the default aging MD5 algorithm.

  1. echo "crypt_default=blf" >> /etc/auth.conf

Enable blf hashing in login.conf as well, along with the UTF-8 character set.

/etc/login.conf
  1. --- login.conf.default 2012-01-02 17:08:05.804291477 -0500
  2. +++ login.conf 2012-01-02 17:08:16.996213774 -0500
  3. @@ -23,7 +23,7 @@
  4. # AND SEMANTICS'' section of getcap(3) for more escape sequences).
  5. default:\
  6. - :passwd_format=md5:\
  7. + :passwd_format=blf:\
  8. :copyright=/etc/COPYRIGHT:\
  9. :welcome=/etc/motd:\
  10. :setenv=MAIL=/var/mail/$,BLOCKSIZE=K,FTP_PASSIVE_MODE=YES:\
  11. @@ -44,7 +44,9 @@
  12. :pseudoterminals=unlimited:\
  13. :priority=0:\
  14. :ignoretime@:\
  15. - :umask=022:
  16. + :umask=022:\
  17. + :charset=UTF-8:\
  18. + :lang=en_US.UTF-8:
  19. #

Rebuild the login database with cap_mkdb /etc/login.conf, then set your new blf-hashed root password with passwd.

Set your time zone information with tzsetup, then create the mail alias database for Sendmail.

  1. cd /etc/mail && make aliases

Configuration

Set your hostname and configure networking in rc.conf. IPv4 can be configured with DHCP, but IPv6 must be configured manually. See Setting up IPv6 on the prgmr wiki. Gigadelic resides in the Fremont datacenter, so this example uses the Fremont IPv6 gateway address.

/etc/rc.conf
  1. hostname="gigadelic.cooltrainer.org"
  2. ipv6_activate_all_interfaces="YES"
  3. ifconfig_xn0_ipv6="2001:470:1:41:a800:ff:fd3e:bc0c"
  4. ipv6_defaultrouter="2001:470:1:41::1"
  5. ifconfig_xn0="DHCP"

You can test your IPv6 setup by ping6-ing a known-v6 host.

  1. [root@gigadelic#nicole] ping6 -c 4 ipv6.google.com
  2. PING6(56=40+8+8 bytes) 2001:470:1:41:a800:ff:fd3e:bc0c --> 2001:4860:4001:800::1014
  3. 16 bytes from 2001:4860:4001:800::1014, icmp_seq=0 hlim=58 time=2.219 ms
  4. 16 bytes from 2001:4860:4001:800::1014, icmp_seq=1 hlim=58 time=2.064 ms
  5. 16 bytes from 2001:4860:4001:800::1014, icmp_seq=2 hlim=58 time=2.141 ms
  6. 16 bytes from 2001:4860:4001:800::1014, icmp_seq=3 hlim=58 time=2.005 ms
  7. --- ipv6.l.google.com ping6 statistics ---
  8. 4 packets transmitted, 4 packets received, 0.0% packet loss
  9. round-trip min/avg/max/std-dev = 2.005/2.107/2.219/0.081 ms

Turn on OpenSSH if you desire remote access. Please realize your SSH daemon will be subject to near-constant automated break-in attempts. Use good passwords, leave AllowRootLogin disabled in /etc/ssh/sshd_config, and consider blocking bad hosts with PF or another firewall.

  1. echo 'sshd_enable="YES"' >> /etc/rc.conf
  2. service sshd start

With that, you’re all done! Fetch a Ports tree with portsnap fetch extract, and install some software.

Notes

Spurious LORs under KERNCONF=XEN

The stock KERNCONF XEN has WITNESS enabled, a debugging feature for lock validation. If you’re running with options WITNESS you may see some spurious LORs related to the filesystem. They’re false positives, as noted in i386/153260, and your system will safely come right out the other end.

  1. # portsnap fetch extract
  2. Looking up portsnap.FreeBSD.org mirrors... 5 mirrors found.
  3. Fetching public key from portsnap2.FreeBSD.org... done.
  4. Fetching snapshot tag from portsnap2.FreeBSD.org... done.
  5. Fetching snapshot metadata... done.
  6. Fetching snapshot generated at Tue Mar 13 00:07:53 UTC 2012:
  7. cbf91c2407f03283d90f5ded759a3af9833e067158f236100% of 66 MB 3469 kBps 00m00s
  8. Extracting snapshot... lock order reversal:
  9. 1st 0xd8459228 bufwait (bufwait) @ /usr/src/sys/kern/vfs_bio.c:2658
  10. 2nd 0xc38db400 dirhash (dirhash) @ /usr/src/sys/ufs/ufs/ufs_dirhash.c:284
  11. KDB: stack backtrace:
  12. X_db_sym_numargs(c03dd42c,c04320d8,c3a19b80,c3a510ac,b395eb11,...) at X_db_sym_numargs+0x146
  13. kdb_backtrace(c018627b,c03e0d7b,c360dae8,c3610a08,e58f2800,...) at kdb_backtrace+0x2a
  14. witness_display_spinlock(c03e0d7b,c38db400,c04047aa,c3610a08,c040442f,...) at witness_display_spinlock+0x75
  15. witness_checkorder(c38db400,9,c040442f,11c,0,...) at witness_checkorder+0x839
  16. _sx_xlock(c38db400,0,c040442f,11c,c3a14e80,...) at _sx_xlock+0x85
  17. ufsdirhash_enduseful(d84591c8,c3a14e80,e58f2930,dd12884c,e58f28d0,...) at ufsdirhash_enduseful+0x2f5
  18. ufsdirhash_add(c3a14e80,e58f2930,84c,e58f28bc,e58f28c0,...) at ufsdirhash_add+0x13
  19. ufs_direnter(c3a51000,c3b07aa0,e58f2930,e58f2bd0,0,...) at ufs_direnter+0x739
  20. ufs_itimes(e58f2bd0,0,e58f2b14,e58f2a78,c03c1bc5,...) at ufs_itimes+0x14bc
  21. ufs_itimes(e58f2b14,e58f2b2c,0,0,e58f2b90,...) at ufs_itimes+0x17d0
  22. VOP_CREATE_APV(c0449ec0,e58f2b14,2,c04059c0,0,...) at VOP_CREATE_APV+0xa5
  23. vn_open_cred(e58f2b90,e58f2c58,1a4,0,c38e5280,...) at vn_open_cred+0x1d3
  24. vn_open(e58f2b90,e58f2c58,1a4,c38f0690,c0a64dd0,...) at vn_open+0x3b
  25. kern_openat(c3a19b80,ffffff9c,2846f1f0,0,a02,...) at kern_openat+0x1ec
  26. kern_open(c3a19b80,2846f1f0,0,a01,1a4,...) at kern_open+0x35
  27. sys_open(c3a19b80,e58f2cfc,c0414576,c03e19be,206,...) at sys_open+0x30
  28. syscall(e58f2d38) at syscall+0x284
  29. Xint0x80_syscall() at Xint0x80_syscall+0x22
  30. --- syscall (5, FreeBSD ELF32, sys_open), eip = 0x2837dd03, esp = 0xbf7fe83c, ebp = 0xbf7fe868 ---
  31. done.
  32. Verifying snapshot integrity...

Updating the kernel

If you want to update your FreeBSD kernel ELF from within FreeBSD itself, install sysutils/e2fsprogs, create a mount point, and mount your ext2 boot partition.

  1. mkdir /root/boot
  2. mount -t ext2fs /dev/xbd0s1 /root/boot

Stability?

FreeBSD has powered gigadelic and this blog for a month now with no panics or other show-stoppers.