The Sigma Designs SMP86xx chips contain, as discussed elsewhere, multiple CPU cores. In addition to the main CPU (a MIPS 74Kf or 24Kf), there are two MIPS 4KEc cores intended for real-time and security processing. These cores are equipped with full MMUs, and are thus perfectly capable of running a Linux kernel.
The real-time (IPU) and security (XPU) processors are normally initialised by the secure boot loader using signed images. Without access to the signing keys, it is thus impossible to run unauthorised code on these by officially supported methods. While the XPU is sufficiently locked down that hijacking it from the CPU is difficult, if at all possible, the IPU offers a backdoor in.
By the time the CPU is booted, the IPU is already running Sigma’s IOS kernel in a protected memory region. This memory is not writable by the CPU, so simply replacing the code is out of the question. However, between the IPU and the system bus is an address remapping unit translating 64MB blocks of CPU physical addresses into different bus addresses by replacing the top 6 bits. The configuration registers for this remapping are accessible to the CPU.
The Sigma kernel sets the IPU EBase to 0x8fb85000, a kseg0 address which is (by necessity) within the range of remapped physical addresses. By reconfiguring the mapping, we can cause the IPU to start executing code of our choosing at the next interrupt. Although the EBase location is cacheable, whatever the Sigma code is doing between interrupts is enough to evict the interrupt handler.
Since almost 64MB of RAM is already set aside for the IPU, it is desirable to run the new kernel there. To this end, I have created a small boot loader as well as a boot loader loader to get it running. The latter, running under Linux on the main CPU, places the kernel in a staging area and installs the IPU-side loader, which copies the kernel to its final destination and jumps to the entry point. The linux-tangox tree can be configured for either the CPU or the IPU.
Exact steps for booting Linux on the IPU:
- Configure and build a kernel for the IPU.
- Build the loaders.
- On the CPU, run ./ipu-load iboot /path/to/vmlinux
If all goes well, some messages should be printed on UART1 (115200, 8n1).
Most of the on-chip peripherals are equally accessible from both CPU and IPU, making it a matter of choice which one is assigned which devices. Needless to say, allowing both to access the same device is not a good idea.