xMach

Back when I started blogging, I started with a few quick things on the top of my head, that being Netware, SIMH, CP/M Zork, Xenix and of course Mach. Back in the shiny new world of 1999 we may have survived the Y2K apocalypses but the valley was firmly set in the mind of start-up fever that would lead to the looming .com crash but the menatlity of IPO & dump would remain to this very day.

The Utah projects around Mach were wound down with the OSKit being the next wave for pistachio, but that set the scene of more than average users now having ‘fast’ machines at their disposal and the ability to rifle though published source and roll their own. It was this environment of trying to make it in the full force of the post ‘year of the desktop’ Linux where xMach appeared, had some interest and quickly died. For the longest time I had thought all evidence of it had been eradicated as the domain had been excluded from wayback, and searching went nowhere. But one bored night I tried exploring sourceforge, a veteran of the pre .com bubble crash to see if it had anything, and yes it did!

https://sourceforge.net/projects/xmach

Oh sure in retrospect it’s pretty obvious. All the cool kids had public repositories on the internet.. And then after the .com implosion so many took their CSV’s and went home. And so many of those just died in selfhosted, self imposed silence.

From what I remember one of the first goals was to time the source to make it easier to cross compile from either NetBSD or Linux, and utilize what was the double edged sword of Lites, the ability to run either 386BSD/NetBSD binaries or Linux binaries. And the Linux side was already incorporating shared libraries something that was desperately needed in 1993 for X11. But this was 2000! And of course the downfall of running Linux under xMach/Lites is that you will of course compare the performance, and Linux won hands down. Not to mention interest in improving and adding to Linux was in full mainstream support by 2000 so it made xMach feel all the more ancient.

But we didn’t come here for practicality!

Getting the source & tools

First off I’m going to use the cross tool chain for building OS Kit. i586-linux2.tar.gz (password and 404 apply) as I not only don’t feel like fighting why MIG doesn’t work in 64bit, and it’s just easier to enable 32bit usermode. Speaking of for Ubuntu 20.04.2:

dpkg --add-architecture i386
apt-get update
apt-get install libc6:i386 libncurses5:i386 libstdc++6:i386 libc6-dev:i386 libfl-dev:i386
apt-get install sharutils gcc-multilib build-essential

And for people like me running on Windows 10, You absolutely MUST enable WSL v2. Without an actual kernel the multiarch simply doesn’t work. No doubt it has something to with actually running Linux vs emulating it. Probably mucking about with the LDT/GDT which you certainly cannot do as a process on Windows.

Next just add the old GCC 2.7.2.3 chain into your path:

PATH=/usr/local/i586-linux2/bin:/usr/local/i586-linux2/lib/gcc-lib/i586-linux/2.7.2.3:$PATH
export PATH

Next up you’ll need the source, and being all new and trendy I put it over on GitHub. Clone the repo, and you are ready to start compiling!

Building the xMach kernel

Make an object directory and run configure like this:

../kernel/configure --host=i586-linux --target=i586-linux --build=i586-linux --enable-elf --enable-libmach --enable-linuxdev --prefix=/usr/local/xmach;cp ../updated-conf/kernel/Makeconf .

For some reason configure never populates the compiler tools right, and I can either mess with autoconf (no thanks) or I can just include a known good file. It’s not hard to figure out, you can diff it if you want to, but it’s just set for a native 32bit build of MIG, and then using the cross tools to build the kernel.

type make, and wait 13 seconds, give or take…

i586-linux-ld -r  -L/home/jsteve/src/xMach/kernel-build/lib -nostdlib \
         -o bsdboot.o crt0.o about_to_die.o anno.o boot_info_dump.o boot_start.o cpu.o cpu_init.o cpu_tables_init.o cpu_tables_load.o crtn.o die.o do_boot.o exit.o gdt.o idt.o idt_inittab.o idt_irq_init.o main.o malloc.o panic.o phys_mem_add.o pic.o putchar.o puts.o real_tss.o real_tss_def.o rv86_real_int.o rv86_real_int_asm.o rv86_reflect_irq.o rv86_trap_handler.o serial.o trap_dump.o trap_dump_die.o trap_handler.o trap_return.o tss.o tss_dump.o -lmach_exec -lmach_c
 make[1]: Leaving directory '/home/jsteve/src/xMach/kernel-build/boot/bsd'
 MACHBOOTDIR=cd /home/jsteve/src/xMach/kernel-build/boot/bsd; pwd \
 /home/jsteve/src/xMach/kernel-build/boot/bsd/mkbsdimage -o /home/jsteve/src/xMach/kernel-build/Mach /home/jsteve/src/xMach/kernel-build/kernel/kernel /home/jsteve/src/xMach/kernel-build/bootstrap/bootstrap
 real    0m13.135s
 user    0m12.060s
 sys     0m1.383s

I cannot stress just how incredibly fast this is. I’m pretty sure it literally took hours for this to run, assuming nothing went wrong, which it almost always did. As part of the fun, next do a ‘make install’

Building Lites

This is somewhat similar to the kernel build, however it is far more touchy. You absolutely MUST copy / fix the Makeconf file otherwise the build will be corrupted and the only way to fix is to remove the build directory and try again.

../lites/configure --host=i586-linux --target=i586-linux --build=i586-linux --enable-mach4 --prefix=/usr/local/xmach --with-mach4=../kernel;cp ../updated-conf/lites/conf/Makeconf conf

And once more again make the project and just wait a few seconds. BSD without the hardware support is pretty tiny

i586-linux-ld -o emulator.Lites.1.1.u3.out ./emulator_base  -L/home/jsteve/src/xMach/lites-build/liblites -L/usr/local/xmach/lib -e __start ecrt0.o  e_mig_support.o emul_generic.o error_codes.o emul_init.o emul_mapped.o emul_misc_asm.o e_bsd.o e_43ux.o bsd_1_user.o emul_mach_interface_user.o e_mach_msg_server.o e_stat.o e_bnr.o emul_exec.o signal_server.o e_uname.o e_mapped_time.o e_sysvipc.o e_linux.o e_sysv.o e_exception.o e_signal.o e_machinedep.o e_linux_trampoline.o e_linux_sysent.o e_isc4_sysent.o e_cmu_43ux_sysent.o e_lite_sysent.o emul_vector.o e_trampoline.o e_linux_getcwd.o    -llites -lthreads -lmach_sa  /usr/local/i586-linux2/lib/gcc-lib/i586-linux/2.7.2.3/libgcc.a && \
 i586-linux-size emulator.Lites.1.1.u3.out && \
 mv emulator.Lites.1.1.u3.out emulator.Lites.1.1.u3
    text    data     bss     dec     hex filename
  130195   16904     160  147259   23f3b emulator.Lites.1.1.u3.out
 make[1]: Leaving directory '/home/jsteve/src/xMach/lites-build/emulator'
 make[1]: Entering directory '/home/jsteve/src/xMach/lites-build/bin'
 make[1]: Nothing to be done for 'all'.
 make[1]: Leaving directory '/home/jsteve/src/xMach/lites-build/bin'
 real    0m6.423s
 user    0m6.006s
 sys     0m0.551s

Yes that’s six seconds. do a ‘make install’ and now your /usr/local/xmach directory is fully populated and ready to transport somewhere to do the ‘install’ and boot.

Installation

One thing to take notice of xMach over the standard last Mach4 is that the Linux boot options have been removed. There is all kinds of changes in 16bit assembly handling that need to be rewritten or fixed. I’m sure someone at some point has, but apparently it’s easier to go with the bsdboot and use either the machboot or GRUB (v1!) to get it going. Although Linux knows how to mount loop ‘diskfiles’ I don’t remember how to deal with partitions and BSD slices. So I did my typical trick of booting up an existing image, and using telnet/uucp to transfer xMach into an existing disk.

Booting however was a bit more fun, as the kernel is now compiled as a BSD ELF image and Grub 1.x won’t boot it. I used a ‘Super Grub2 disk hybrid‘ ISO image, and was able to just hit escape and type in:

kfreebsd (hd0,msdos2,bsd1)/Mach
boot
Booting xMach kernel

Because of the massive drift in multiboot vs ‘BSD ELF’ the drive isn’t passed correctly so I have to manually tell it ‘/dev/hd0a/mach_servers’ and it’ll pick up Lites, and boot up!

And there we go, with my old Mach4/Lites image from 2009 with a ‘fresh’ cross compiled build from Windows 10 / Ubuntu 20.04

Where to go from here?

Realistically, nowhere. Seven years ago there was OpenMach, which seems to have done a few things, but even moving to a GAS from 2015 didn’t help me at all trying to build the 16bit stuff so the answer must lie in the past. Otherwise the fundamental problem as always is at best you will have a 4.4BSD system which again in 1992 would be awesome, but 2021? yeah it’s a curiosity at best.

I was looking back at old posts

And I saw my old look at Mach+Lites.  And of course there was a qcow disk image associated with some ancient version of Qemu which I can’t run on Wine on OS X.  So I figured with a bit of fun I’d update the disk image to work with Qemu 1.7.0.

Luckily Qemu 0.15.1 works just fine for it’s qemu-img.  So a quick

qemu-img convert -f qcow -O vmdk mach.img mach.vmdk

and I had my image.  I’m not sure of what the NE2000 parameters that Mach can use to enable the network, but I do recall it was easier to just rebuild Qemu around them.  However this time, I switched to the Mach kernel that utilized Linux device drivers to get a working network.

I updated the hard disk file here.

Screen Shot 2013-12-27 at 12.16.18 AM

For the two or three people who care about BSD evolutionary dead ends.

A tale of two kernels.

Back in the early 1990’s Microkernel’s were all the rage. Everywhere you would go you’d hear all about Pink, Taligent, Windows NT, and the grand daddy of them all Mach.

Probably the most well known debate about microkernel vs monolithic kernels was the Tanenbaum vs Torvalds debate that raged on comp.os.minix back in 1992. You can read the entire thing here : ( http://www.oreilly.com/catalog/opensources/book/appa.html ). It was interesting in the sense that even Ken Thompson of UNIX fame even chipped in. Tanenbaums’s major points were that a microkernel is more inherently portable than a monolithic kernel, and that microkernels could be more reliable, and easier to maintain. Of course more than 10 years later we can see that Linux still flourishes, and that outside of Windows NT & OS X no mainstream OS relies on a microkernel. Even OS X treats mach more as a call library than a traditional microkernel, since all of the exe’s in Darwin / OS X are Mach-O format, not COFF/ELF,A.OUT, etc etc.

Mach started out as a project from CMU derived from the UNIX source code, to try to re-invent the lower levels of UNIX into something that would scale easier to multiprocessors, support for threads, and the holy grail of them all, expand it’s portability. Sadly the first few versions of Mach are barred from distribution due to their inclusion of encumbered UNIX source code. However when the university of Utah picked up Mach, and released Mach4 (UK22, info here http://www.cs.utah.edu/flux/mach4/html/Mach4-proj.html ), including full source. Also they provided Lites, a BSD server that can run atop Mach, giving the user a ‘UNIX’ system, as it were.

Lites

Lites

So digging through some network groups, and testing stuff, I finally slapped together the pieces, and built a Mach/Lites system on NetBSD 1.1 . And how does it perform? It’s significantly slower than NetBSD is. You can tell that the amount of context switching involved in Mach as a program makes a call the microkernel, which in turn validates & passes it to the server, which further validates, runs the process, then sends the results back to the kernel, which then passes it back to the program. I’ve heard in a worse case scenario a 500% reduction in speed. You can always read more info on the fine wiki article here ( http://en.wikipedia.org/wiki/Mach_kernel ).

Lots of people will argue that microkernel’s have simply failed, and that it’s simply an example of what seemed like a good idea being pushed too hard once it was found to fail. It a lot of ways it reminds me of ADA.

So for now I’m going to provide a Qemu image of Lites running on Mach 4. unzipping the file will provide you with a lites.cmd file which for windows users you can just run directly. Things to note are:

-The version of Qemu that I’ve bound requires libpcap to be installed.
-Mach4 can only address 16mb of ram, due to DMA issues across the 16mb line.
-I’ve enabled user mode networking so that
-the cmd file sets up local port 23 to be redirected to the VM. This will allow you to telnet in simply by ‘telnet localhost’. You may want to use putty for better terminal handeling
-The included Gcc 2.4.5 is ancient. Outside of building a simple irc client, I wouldn’t expect much.
-The boot process is broken, and it’ll parse through the rc scripts twice. Just let it do it’s thing, and it’ll drop to a login prompt.

Logging into Lites/NetBSD

Logging into Lites/NetBSD

Other than that it behaves just like a NetBSD 1.1 machine.

Notice that grub boots the kernel /Mach.UK22 . When Mach boot’s it’ll load up the files emulator & startup. The ‘emulator’ is the Lites microkernel. Once it’s loaded it’ll start mach_init which just symlinks to /sbin/init and the normal NetBSD bootup will commence.

You can download my image directly here as MachUK22-lites-nat.zip.

Next time we’ll play with SLS Linux.