Skip to main content

Running an Ubuntu ppc64le virtual machine on x86

For an issue I'm debugging, I need a 64-bit little-endian powerpc machine. I don't have a physical one handy, so I wanted to run a virtual one on an x86 system.

We can use qemu and libvirt for this. Unfortunately, it will be very slow - we have to use qemu's TCG mode rather than hardware assisted virtualisation because the guest (POWER) and host (amd64) are different. Fortunately, libvirt can work with these VMs like normal, which I find very helpful as it allows me to use tools like virsh and virt-manager, rather than dealing with qemu's inscrutable command line arguments.

So I grabbed an Ubuntu ppc64el install ISO (Xenial, Bionic) and set to work.

Here's the virt-install incantation derived from much accumulated wisdom amongst my former colleagues at OzLabs:

virt-install --arch=ppc64le --name=GUESTVMNAME \
  --os-variant=linux --boot menu=on \
  --disk path=GUESTDISK.qcow2,size=20,format=qcow2,bus=virtio,cache=none,sparse=true \
  --memory=4096  --vcpu=2  --wait 0  --graphics none \
  --cdrom=/home/ubuntu/ubuntu-18.04.1-server-ppc64el.iso

If you run this on an x86 Xenial host, the installation will begin and you can interact with it by running virsh console (or use virt-manager).

Sadly, it does not work; the installer kernel panics. Removing 'quiet' from the boot commands in grub shows messages like the following:

modprobe[98]: unhandled signal 4 at 00007d96d2364fbc nip 00007d96d2364fbc lr 00007d96d2332ab8 code 1

Mikey Neuling pointed out that this was a SIGILL - illegal instruction - which reminded me that while Ubuntu only supports POWER8 for ppc64el, qemu will emulate a lot further back - and by default on Xenial I guess it uses an older ISA.

So I manually set the machine type to POWER8. I used virt-manager, which generated this snippet of libvirt xml under the domain tag:

  <cpu mode='custom' match='exact' check='none'>
    <model fallback='allow'>POWER8</model>
  </cpu>

This, however, won't start - virsh start and virt-manager report:

qemu-system-ppc64le: No Transactional Memory support in TCG, try cap-htm=off

Suraj Jitindar Singh explained some of the backstory here, and suggested that I try specifying a particular "machine type" to qemu that would default to having hardware transactional memory off. Fortunately, his suggestion - pseries-2.12 - worked: the machine started, the installer is installing, and I'm much happier.

I used virsh edit to do this - the relevant snippet is:

    <type arch='ppc64le' machine='pseries-2.12'>hvm</type>

This lives under os, under domain.

The story on Bionic

Fortunately Bionic does a better job of all this.

The virt-install command fails straight out of the box with the cap-htm error. Fortunately, it's easy to specify the machine type for virt-install: just append --machine=pseries-2.12:

virt-install --arch=ppc64le --name=GUESTVMNAME --machine=pseries-2.12 \
  --os-variant=linux --boot menu=on \
  --disk path=GUESTDISK.qcow2,size=20,format=qcow2,bus=virtio,cache=none,sparse=true \
  --memory=4096  --vcpu=2  --wait 0  --graphics none \
  --cdrom=/home/ubuntu/ubuntu-18.04.1-server-ppc64el.iso

This works! I suppose the machine type must imply a POWER8 cpu, because I didn't need to specify it.

Update

With a bionic guest, the installation worked on the serial console, but systemd failed to spawn a terminal on it for some reason. At least, it's probably systemd's fault, and it's convenient to blame it! I haven't actually confirmed this: I added a display in virt-manager and installed an openssh server so I can now access it in 2 different ways.

See also
  • uvtool: I normally use this for my VMs, but it has some issues starting ppc64 guests. It flat-out fails on Xenial (it starts it as an x86 guest!) and on Bionic it fails too - it seems to assume that it will be running under KVM. I haven't dug into this any further.
  • The very helpful instructions from Michael Ellerman on the linuxppc/linux wiki: Booting with Qemu. If I didn't need a pretty expansive user-space I would totally have just used this.

Comments

Popular posts from this blog

Connecting to a wifi network with netplan

How do you connect to a a wifi network with netplan? I hang out on the #netplan IRC channel on Freenode, and this comes up every so often. netplan - the default network configuration tool in Ubuntu 17.10 onwards - currently supports WPA2 Personal networks, and open (unencrypted) networks only. If you need something else, consider using NetworkManager directly, or falling back to ifupdown and wpa_supplicant for a little longer. Without further ado, here are tested, working YAML files for connection to my local WPA2 and unencrypted network. The only things that have been changed are the SSIDs and password. Both networks have a router providing dhcp4. In both cases I assume there's only one wifi device in the system - if this is not true, replace match: {} with something more specific. You can drop these in  /etc/netplan and run netplan generate; netplan apply  and things should work. The network will also be brought up on subsequent boots. Note that, as always in YAML...

Anonymous bridges in netplan

netplan is the default network configuration system for new installs of Ubuntu 18.04 (Bionic). Introduced as the default in Artful, it replaces /etc/network/interfaces . One question that gets asked repeatedly is: "How do I set up an anonymous bridge in netplan?" (An anonymous bridge, I discovered, is one where the bridge doesn't have an IP address; it's more akin to a switch or hub.) It's been approached on  Launchpad , and comes up on the IRC channel. If you're trying to create a bridge without an IP address, the obvious first thing to try is this: network: version: 2 ethernets: ens8: match: macaddress: 52:54:00:f9:e9:dd ens9: match: macaddress: 52:54:00:56:0d:ce bridges: br0: interfaces: [ens8, ens9] This is neat, plausible, and wrong - the bridge will be created but will stay 'down'. Per ip a : 5: br0: <BROADCAST,MULTICAST> mtu 15...

Painless powerpc cross-compiling

As an ex-IBMer, I'm still quite fond of POWER/ppc64 processors, and occasionally cross-compile kernels for 64-bit little-endian PowerPC (ppc64el/ppc64le) from my amd64 system. It's not immediately obvious what the simplest way to do this is. On Ubuntu (and I'm told, Debian) it is really very simple. Installation sudo apt install gcc-powerpc64le-linux-gnu Congrats, you now have a ppc64le cross-compiling toolchain installed! If you need other languages, g++/gccgo/gfortran/gnat/gobjc-powerpc64le-linux-gnu are also available. Kernel cd your/linux/source make ARCH=powerpc CROSS_COMPILE=powerpc64le-linux-gnu- <your usual kernel build commands here> That's it. Userspace It depends a bit on the build system. Here's how to build, for example, sed , which uses autotools ( ./configure and friends). ./configure --host powerpc64le-linux-gnu make That's it.  For a dynamically linked binary, you only need the headers for any library depende...