Design a site like this with WordPress.com
Get started

(Almost) Emulating the 68 Katy

During a recent bout of illness I became fascinated with the concept of porting the Linux kernel to minimalist environments: it began when I stumbled upon this video of someone who had gotten Linux running on their RISC-V emulator, which made me wonder if I could do the same with my 68000 emulator.

Unfortunately, I am not familiar with porting Linux at all, and with my 68000 emulator not being very mature, I wasn’t sure if it was even capable of running Linux in the first place; if I encountered a crash, how would I know if it’s an issue with the Linux port or my emulator?

So it looked like this idea wasn’t going to pan out… but wait – what if I instead emulated an existing 68000 Linux port that I know already works?

While researching how to cross-compile Linux for the 68000, I read this series of blog posts about a 68008-based computer that was originally designed on a breadboard – the 68 Katy. It was amazing to see how similar wiring an old CPU up to ROM/RAM chips and some peripheral devices was to what I’d done with a PIC microcontroller back in university. I guess I figured that CPUs wouldn’t be as simple. Anyway, the blog posts provided a pre-built copy of the 68 Katy’s Linux port (complete with a bootloader and filesystem) in a single flat-mapped binary blob that was ready to be placed at the start of the 68000’s address space – it couldn’t be any simpler! All I’d have to do is implement the 68 Katy’s memory map and serial communication port, and I could run this blob in my emulator!

Oh, right, there was one feature that I needed to add to my 68000 emulator first: user mode. Previously, my emulator had only ever ran software that operated in supervisor mode, but Linux extensively makes use of user mode, which has its own unique stack pointer and raises exceptions if certain privileged instructions are used. Implementing this was simple enough, but it took a while to weed-out the subtle bugs.

With this last feature added, I could proceed to emulating the 68 Katy!

My 68000 emulator is actually just a part of my Mega Drive emulator – clownmdemu – but each component of my Mega Drive emulator was designed to be modular and usable independent from the rest of the project. It definitely paid off in this case, as it was easy to pluck out the 68000 emulator and begin wiring it up to a new environment: all it needs is some initialisation and two call-back functions for reading and writing memory.

The memory map is simple: 0x00000-0x77FFF for ROM, 0x78000-0x7FFFF for IO, and 0x80000-0xFFFFF for RAM. The serial communication port exists in the IO space, and was pretty complicated to implement: the actual device on a 68 Katy is an FT245, but all that really matters is that it’s a FIFO with a couple of status bits to say when there’s pending data to be read, or no more room in the FIFO for data to be written. Figuring out the details required reading the code of the 68 Katy’s system monitor (which is written in pure, largely-undocumented assembly), the FT245’s manual, and the FT245’s kernel driver.

With this implemented, I was able to boot the 68 Katy binary blob and enter the system monitor. At first, my emulator only had support for serial output, so I couldn’t give any input, but I could at least see the monitor boot and print a message. Unfortunately, input is required to make the monitor boot the Linux kernel. Once I had input working, I was able to boot the kernel by entering the command ‘j003000’ (jump to address 0x003000, which is where the kernel’s code begins in the binary blob).

At first, this resulted in an immediate crash, but this turned out to just be the effect of a bug in the memory map implementation (IO was being mapped to ROM – oops). With that addressed, the kernel was able to print a few messages before hanging on ‘Calibrating delay loop..’.

This same issue was detailed in the 68 Katy’s development blog: Linux apparently needs a timer interrupt in order to do stuff. The 68 Katy has a timer wired up to the 68008’s interrupt pins, raising a level 5 interrupt every 100th of a second. Once that was recreated in my emulator, Linux was able to proceed a little bit further.

After hours of debugging, I found that this hang is caused by a failure to create the kernel thread which is responsible for running the ‘init’ function, which presumably completes the rest of Linux’s initialisation process. The thread is unable to be created because a call to ‘kmalloc’ fails to allocate memory. Unfortunately, this is where the extent of my debugging abilities end.

I can only imagine that my 68000 emulator has a bug in it, which somehow is not exposed when running any of the Mega Drive games and homebrew that I have on hand. I was hoping that any inaccuracies in my emulator would result in easily-debugged hard crashes rather than an insidious little state corruption like this.

The best way that I can think of to debug this is to swap out my 68000 emulator with one that I know is accurate, and then compare various ‘kmalloc’-related variables at various points throughout the boot process, but that doesn’t sound like the most fun. Admittedly, a proper test suite for my 68000 emulator would help a lot to find inaccuracies. I wonder if there’s anything like the Z80’s ‘ZEXALL’ instruction set exerciser for the 68000…

Advertisement

One thought on “(Almost) Emulating the 68 Katy

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: