Getting closer to Classic on Linux on ppc64le

A recurring theme here is my personal opinion that OpenPOWER workstations like the Raptor family (particularly now that the Blackbird is a lower-cost option) are the Power Mac successors Power Mac holdouts should embrace. It's the same processor family, it's an open system, and Raptor machines have that pride of hand-built quality and solid engineering we got accustomed to with our G4 and G5 machines. We're still missing the ability to use KVM-PR to boot Mac OS 9 in QEMU on OpenPOWER systems, but with recent improvements in QEMU and a few third-party assists, I'm now to the point where I can nevertheless use my old Mac OS 9 apps productively like FrameMaker and Photoshop 7. If you run your own QEMU builds with -O3 -mcpu=power9 performance is more than enough for these apps and you can get the work done well. In the screenshot you can see me using Photoshop to make a demo image and saving it to the shared folder, which I then opened up in GNOME's image viewer to prove it transferred over. Et voila.

There are still some pain points left (other than the lack of working KVM-PR in Mac OS 9); sound is still somewhat of a work in progress if it works at all and there is no copy-paste. Many games won't work properly either. However, QEMU Mac OS 9 guests can (with assistance) now support tablets with now much more natural mouse movement, using ndrv you can run at multiple convenient resolutions, files can be exchanged over AFP via Netatalk, and if you're willing to put up with a little clock madness QEMU can "sleep" so that you're not sucking CPU cycles in the background.

You'll need an ISO and/or CDROM of Mac OS 9 to get started. I won't provide you this and merely assume you have a perfectly legal source for one, such as ripping the installation CD you already own. (I own several.) Some of these steps I've already gone through in our earlier QEMU articles but they are reproduced here for convenience. These instructions are not OpenPOWER-specific in general and should work for other Linux systems (I'm on Fedora).

  • Create your disk image, usually qemu-img create -f qcow2 classic.img 40G or some such. We will refer to this image as classic.img in the example commands below.

  • If not already configured set up tap networking, typically with something like this for tap0, with your username being billg:

    sudo ip tuntap add dev tap0 mode tap user billg
    sudo ip link set tap0 up promisc on
    sudo brctl addif virbr0 tap0
    (optional, but handy for libvert)

    This will persist until reboot.

  • Download the custom video driver qemu_vga.ndrv from Github. I put it in ndrv/qemu_vga.ndrv.

  • Set up your initial boot string. Mine looks like this, assuming you're booting from your Mac OS 9 ISO (in iso/922.iso):

    qemu-system-ppc -M mac99,accel=tcg,via=pmu -m 1536 -drive id=root,file=classic.img,format=qcow2,l2-cache-size=4M -usb -netdev tap,id=mynet0,ifname=tap0,script=no,downscript=no -device rtl8139,netdev=mynet0 -rtc base=localtime -L ndrv -prom-env resolutions=640x480,800x600,1024x768,1152x864,1280x800,1440x900,1920x1080 -boot d -cdrom "iso/922.iso"

    This gives you the maximum 1.5GB of RAM Mac OS 9 supports. You'll notice we haven't enabled the tablet yet; we'll get to that.

  • Start up Mac OS 9 and install to your hard disk. When this is done, shut down the emulated Mac (QEMU will close).

  • Download our "essentials" ISO from the Floodgap gopher server (Firefox will need either OverbiteWX or OverbiteNX). It contains this USB tablet driver, the freeware 1.4 version of USB Overdrive, the Network Time control panel (for talking to RFC 868 and NTP servers) and an RTL8139 Ethernet extension. Uncompress it and bring up your system booting from the hard disk image but with the ISO ready. We'll assume it's in iso/essential.iso:

    qemu-system-ppc -M mac99,accel=tcg,via=pmu -m 1536 -boot c -drive id=root,file=classic.img,format=qcow2,l2-cache-size=4M -usb -netdev tap,id=mynet0,ifname=tap0,script=no,downscript=no -device rtl8139,netdev=mynet0 -rtc base=localtime -L ndrv -prom-env resolutions=640x480,800x600,1024x768,1152x864,1280x800,1440x900,1920x1080 -cdrom "iso/essential.iso"

  • Mac OS 9 should have StuffIt Expander built-in. Uncompress USB Tablet and put it in the System Folder's Startup Items (it's an app, not an INIT or CDEV). Uncompress the RTL8139 extension and put it in System Folder, Extensions. The others are optional but recommended; uncompress and install as they direct. Set your desired screen resolution of the ones available (I use 1440x900 on my 1080p display) and shut down again. Here's our last boot string change, adding the tablet this time:

    qemu-system-ppc -M mac99,accel=tcg,via=pmu -m 1536 -boot c -drive id=root,file=classic.img,format=qcow2,l2-cache-size=4M -usb -netdev tap,id=mynet0,ifname=tap0,script=no,downscript=no -device rtl8139,netdev=mynet0 -rtc base=localtime -L ndrv -prom-env resolutions=640x480,800x600,1024x768,1152x864,1280x800,1440x900,1920x1080 -device usb-tablet

    Incidentally, if you want to build the USB Tablet app yourself, I was able to do so by downloading the project, resource and source file, converting the .r and .c files to Mac line endings, and opening the project in CodeWarrior 7 on my MDD G4.

  • Mac OS 9 will now boot up, and once USB Tablet is run, your mouse will suddenly switch to tablet mode. No more mouse grabbing needed. Nice!

Since I have GNOME set to respond to some muscle-memory key sequences like Command-Q (to close the window), I created an appmodmap bit for QEMU so that Command-Q would be passed to the emulated Mac and only Ctrl-Command-Q would actually quit QEMU. A command like gsettings set org.gnome.desktop.wm.keybindings close "['<Ctrl><Super>Q']" & should do it too.

The next thing to do is get networking operational, because this is how we'll share files. Regular EtherTalk doesn't work but AFP-over-TCP does and Netatalk supports it. (You could of course install something like DAVE and use samba, but Mac OS 9 has AFP-over-TCP support built in and Netatalk preserves resource forks.)

  • Configure your network within Mac OS 9 from the TCP/IP control panel. As we have it configured here it should be sufficient to just get an address over DHCP (from QEMU).

  • Set up Netatalk. Depending on how it's built you may or may not get any of the authentication options to work; mine didn't with the Fedora package even though the emulated Mac could talk to my usual Sawtooth G4 fileserver with a password. I eventually just set up guest access to a single interchange folder that runs as me, because all of my office systems including the T2 are on an independent non-routable network (if you don't have such a setup, consider binding it to an internal interface only). /usr/local/etc/afp.conf thus looks like this, assuming your username is billg:

    ; Global server settings
        vol preset = my default values
        afp interfaces = enP4p1s0f0
        uam list =
        guest account = billg

    [my default values]
        appledouble = ea
        ea = samba

        basedir regex = /home

    [HFS Work Area]
        path = /home/billg/HFS

    This way some malicious Mac program (or more likely me fatfingering something) can't do anything more than trash the HFS folder from QEMU. enP4p1s0f0 is the NIC on the local network (from ip addr).

  • Go to the Chooser. Click AppleShare (notice no servers appear, even if you set AppleTalk to Ethernet) and then the Server IP Address button, and enter your host machine's local address. If you used my example above, connect as guest and you'll get offered a drive called "HFS Work Area." Open that and you will now have file sharing operational.

  • Finally, let's make it automatically mount. Since it's connected as a guest we need not preserve credentials because there are none to preserve (you could, if you wanted to, in the Mac OS 9 keychain). Make an alias of the network mount and drop it into the Servers folder in your emulated Mac's system folder. Shut down the emulated Mac and restart QEMU; the drive should automount, allowing you to instantly interchange files back and forth.

One more nice thing, which is optional, is to sleep the emulation when not in use. Sleeping from the Finder (i.e., Special, Sleep) doesn't work because the "lid is not closed" [sic], so to do this go to QEMU's Machine menu and check Pause. This does have a couple side effects, namely that after a few minutes the AppleTalk connection will be severed and the time will be wrong, since the clock doesn't resync. To reconnect the AppleTalk connection go to the Apple Menu, Recent Servers and select it; it will reopen.

The time is a little trickier. Mac OS 9 will talk to NTP servers, but it doesn't sync on demand, thus the Network Time CDEV we offered on the Essentials ISO. Not only will this let you fix the time right away (Apple Menu, Control Panels, Network Time and click Set Time) but you can also adjust for post-2002 daylight savings in your locale by defining a new, corrected timezone.

Once we figure out the issues with split-hack and KVM-PR, we should be able to get a dramatic speed boost on OpenPOWER systems. But even as it is, the software runs well and my sizeable investment in classic Mac applications is preserved. Sure, you could do this on a PC or a modern Mac, but I'd rather do it on what every Power Mac wants to be when it grows up (and when virtualization is working should be even better).


  1. Please don't name image files that are QCOW2 IMG, that is normally used for raw image files that can be directly accessed via "fdisk -l [IMAGE FILE]" then "mount -o loop,offset=$((512*)) /mnt"

    guestfish and guestmount can be used with FUSE to open qcow2 files, but they are wildly inefficient (they spin up an emulation in QEMU and communicate with FUSE over a network socket). I prefer to use QEMU's qemu-nbd to create temporary filesystem /dev devices to attach (partprobe them if partitions don't show up initially) as it is faster and smoother in my experience.

    In addition to being sparse, the QCOW2 format is capable of compression, just not in an initial or on-the-fly image (to my knowledge), but you can convert it to compress it "qemu-img convert -O qcow2 -c " the -c flag will cause it to compress the data in the new QCOW2, and the original file doesn't have to be a QCOW, so you can convert VMDKs or raw images to it as well.

    As for virtualization, my current experiments on it with my Blackbird only allow KVM to be used if using the exact host chip. So as far as I can tell, virtualization will always give the guest a POWER9 in my case. Still it's an interesting avenue, and I wonder if the endianess will be a problem, since there's a kernel flag for KVM to allow for cross-endian virtualization, and I don't know if that's turned on, or how to use it.

    1. I'm going to politely disagree with you on .img. There are lots of things that end in .img, not just that restricted usage.

      As for virtualization, you're talking about KVM-HV. Mac OS 9 will only work with KVM-PR, which can emulate any PowerPC chip, including big-endian ones. See prior articles in this series for its limitations, including that you need to run it in HPT instead of radix MMU mode.

    2. Now KVM-PR is something I definitely need to look into. Unfortunately at current using modprobe -r kvm_hv causes kernel panics and soft lockups on cores until a reboot on my Fedora 31, so I'll have to take some time later and investigate some more. Trying to use kvm with both enabled on qemu-system-ppc tells me it isn't there, and using it with defaults on qemu-system-ppc64 is definitely using kvm_hv. I'll have to mess around with rd.blacklist and the blacklists files later to see if I can get kvm_pr working properly on my system.

    3. Not sure why modprobe -r kvm_hv is giving trouble, but you can't run KVM-PR in radix MMU mode, and Fedora defaults to radix. You can only run it by putting the kernel in HPT mode.

    4. Sorry, I had disabled that. I've also finished my blacklisting of the kvm_hv module. The result is puzzling, but may be a regression since your last article.

      [min@thea ~]$ grep MMU /proc/cpuinfo
      MMU : Hash
      [min@thea ~]$ lsmod | grep kvm
      kvm_pr 144641 0
      kvm 365360 1 kvm_pr
      [min@thea ~]$ ls -l /dev/kvm
      crw-rw-rw-. 1 root kvm 10, 232 Mar 31 16:28 /dev/kvm
      [min@thea ~]$ groups
      kvm disk wheel min dialup
      [min@thea ~]$ qemu-system-ppc -enable-kvm
      qemu-system-ppc: -machine accel=kvm: No accelerator found
      [min@thea ~]$ qemu-system-ppc64 -enable-kvm
      qemu-system-ppc64: warning: Failed to set KVM's VSMT mode to 8 (errno -22)
      qemu-system-ppc64: No large decrementer support, try cap-large-decr=off
      [min@thea ~]$ qemu-system-ppc64 --version
      QEMU emulator version 4.1.1 (qemu-4.1.1-1.fc31)
      Copyright (c) 2003-2019 Fabrice Bellard and the QEMU Project developers
      [min@thea ~]$

    5. Bad news: I could confirm your issue with modprobe -r kvm_hv. I sent that to the KVM folks, it looks like a kernel bug.

      Good news: You don't have to remove or blacklist it. If you take the examples from the previous articles (under the KVM category) and change qemu-system-ppc to qemu-system-ppc64, as long as you specify the CPU (e.g., -cpu nitro) it will automatically use PR when necessary. I was able to successfully boot my Tiger VM with KVM-PR that way.


Post a Comment

Comments are subject to moderation. Be nice.