Saturday 29 May 2021

Linux for SPARC64 on QEMU

Linux for SPARC64

Linux is an open source UNIX-like operating system kernel that supports a wide range of platforms. This includes the 64-bit SPARC platforms (sparc64), commonly seen in Sun Microsystems UNIX workstations and servers.

Since SPARC64 processors support both 32-bit and 64-bin SPARC binaries, Linux distributions for SPARC based systems can come in three broad classes:

  1. 32-bit kernel with 32-bit user-land - 32-bit & 64-bit SPARC processors
  2. 64-bit kernel with 32-bit user-land - 64-bit SPARC processors
  3. 64-bit kernel with 64-bit user-land - 64-bit SPARC processors

The Debian Linux distribution has provided for all three of these scenarios with its 'sparc' and 'sparc64' ports:

Since the 'sparc64' in-official port provides the most recent Linux version, and is fully 64-bit and thus provides more of a contrast with the 32-bit Linux environment used in Linux for SPARC (32-bit) on QEMU (sun4m) - System Information, it's our selected target.

QEMU and SPARC64

QEMU provides SPARC64 system emulation for PCI based 'sun4u' and 'sun4v' systems. The 'sun4u' platform includes the Sun Ultra workstations. The default QEMU emulation looks most similar to the Sun Ultra 5 and Ultra 10 workstations (Wikipedia), which are machines that many people are familiar with thanks to their popularity in tech companies in the late 1990s and early 2000s. So let's go with the 'sun4u' system emulation:

  • CPU: TI UltraSPARC IIi (SUNW,UltraSPARC-IIi)
  • RAM: 128 MiB default, max. > 4 GiB
  • Disk controller: PATA
  • Network controller: Sun "Happy Meal" Ethernet (hme0)
  • Graphics: generic VGA with VESA support

Since modern operating systems like memory, I'm going to give the emulated system 1 GiB (1024 MiB) of memory. Apparently this will also avoid issues with the memory usage of the Debian installer.

Installing Linux

First step is to create a directory for the various files:

$ mkdir sparc64_Debian_Linux
$ cd sparc64_Debian_Linux

disk image for the installation. For this I'm going to use a 8 GiB qcow2 format disk image:

$ qemu-img create -f qcow2 hda_debian_sparc64.qcow2 8G

Now let's download the current installation CD:

$ wget https://cdimage.debian.org/cdimage/ports/current/debian-10.0.0-sparc64-NETINST-1.iso

Okay we've now got the disks, so on to building the QEMU command for installation:

$ qemu-system-sparc64 \
    -m size=1024M \
    -hda hda_debian_sparc64.qcow2 \
    -cdrom debian-10.0.0-sparc64-NETINST-1.iso \
    -net nic \
    -net user \
    -vga none \
    -boot once=d \
    -name 'Install Debian Linux on UltraSPARC'

The default graphics adapter has issues on this platform, so we remove it with the -vga none option, we will use the serial console (ctrl-alt-2) to interact with the installation. The -boot once=d option is used to tell the OpenBIOS firmware to boot from the installation CD for the first boot, any subsequent reboots will use the main disk instead.

The installation is Debian standard, so I'll only mention the bits that deviate from the normal flow of the installer...

At the "Finish the installation" stage, don't select "Continue" but instead hit Esc to get to the main installation menu. Select the "Execute a shell" option so we can get a command-line and make some changes...

Thanks to the Debian Sparc64 QEMU notes (Sparc64Qemu) and a thread on the debian-sparc mailing list (https://www.mail-archive.com/debian-sparc@lists.debian.org/msg27299.html) we know there is a issue with some modules in the kernel and their interaction with the QEMU default graphics card. Since we are running without the graphics card there shouldn't be a problem, but just in case we accidentally boot with graphics enabled we need to prevent those modules from loading.

# echo 'blacklist bochs-drm' > /target/etc/modprobe.d/drm-blocklist.conf

Now we can exit the shell (ctrl-D or exit) and finish the install. Once back at the menu, the "Finish the installation" option is selected, so hit enter and hope...

And the reboot fails with a kernel panic! But we're installed, so not a big deal (although it would be nice if it worked).

Attempting a direct boot (command line as above but with -boot c) manages to load the boot loader (Grub) but it then fails with a "error: canonicalise devname failed." This is a known issue (see qemu-system-sparc64 not booting install of debian sparc64) that can be worked round by using the QEMU's ability to directly boot a kernel. To do that we need to get the kernel and RAM disk image from the installation.

Extract the Kernel & Ramdisk

I'm going to use the libguestfs tools to access the image.

First create a mount point:

$ mkdir tmp_mnt

Then mount the /boot partition (sda1) on the mount point:

$ guestmount -a hda_debian_sparc64.qcow2 -m /dev/sda1 tmp_mnt

Identify the required files:

$ ls -l tmp_mnt
total 76766
-rw-r--r-- 1 root root 169558 Jan 30 20:38 config-5.10.0-3-sparc64
-rw-r--r-- 1 root root 169464 May 28 09:31 config-5.10.0-7-sparc64
drwxr-xr-x 5 root root 1024 May 29 11:49 grub
lrwxrwxrwx 1 root root 27 May 29 08:22 initrd.img -> initrd.img-5.10.0-7-sparc64
-rw-r--r-- 1 root root 22647626 May 29 00:39 initrd.img-5.10.0-3-sparc64
-rw-r--r-- 1 root root 22667406 May 29 08:38 initrd.img-5.10.0-7-sparc64
lrwxrwxrwx 1 root root 27 May 29 00:26 initrd.img.old -> initrd.img-5.10.0-3-sparc64
drwx------ 2 root root 12288 May 28 23:35 lost+found
-rw-r--r-- 1 root root 83 Jan 30 20:38 System.map-5.10.0-3-sparc64
-rw-r--r-- 1 root root 83 May 28 09:31 System.map-5.10.0-7-sparc64
-rwxr-xr-x 1 root root 16279624 Jan 30 20:38 vmlinux-5.10.0-3-sparc64
-rwxr-xr-x 1 root root 16342448 May 28 09:31 vmlinux-5.10.0-7-sparc64
lrwxrwxrwx 1 root root 24 May 29 08:22 vmlinuz -> vmlinux-5.10.0-7-sparc64
lrwxrwxrwx 1 root root 24 May 29 00:26 vmlinuz.old -> vmlinux-5.10.0-3-sparc64

We want to current kernel as linked to by vmlinuz, and the init RAM disk image as linked by initrd.img:

$ cp tmp_mnt/initrd.img-5.10.0-7-sparc64 tmp_mnt/vmlinux-5.10.0-7-sparc64 ./

Then un-mount the disk image:

$ guestunmount tmp_mnt

So we now have the bits to boot the system.

Boot the Installed System

Now we can boot the kernel in QEMU:

$ qemu-system-sparc64 \
    -m size=1024M \
    -hda hda_debian_sparc64.qcow2 \
    -cdrom debian-10.0.0-sparc64-NETINST-1.iso \
    -net nic \
    -net user \
    -vga none \
    -kernel vmlinux-5.10.0-7-sparc64 \
    -initrd initrd.img-5.10.0-7-sparc64 \
    -append 'console=ttyS0 root=/dev/sda2' \
    -name 'Run Debian Linux on UltraSPARC'

And we're up and running.

User Networking and ssh

Since I'm using the QEMU user-mode networking, use of ssh needs a little bit of port mapping. The ssh protocol uses port 22, so we'll need mappings to:

  • Provide a mapping from an IP in the guest network to the ssh port on the host
  • Add a port on the host that maps on to the guest

To do this we can use QEMU's network forwarding options and the netcat command to do a little forwarding:

-net "user,guestfwd=:10.0.2.1:22-cmd:netcat 127.0.0.1 22,hostfwd=::2222-:22" \

This can be put in place of the -net user part of the QEMU command.

Then the host can ssh to the guest with:

$ ssh -p 2222 localhost

And the guest can ssh to the host with:

$ ssh 10.0.2.1

As well as ssh this also supports scp, so moving files between host and guest is easy.

Further Information & Sources

Sources of more information:


No comments: