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.
I downloaded a zip of your kernel branch from GitHub, and I’ve been trying to compile it using the standard Debian cross compiling tools from apt. I got through main kernel compilation after dealing with my toolchain not handling maddu well, which was only found in btrfs, xfs, and dccp support. However, when trying to build modules for the kernel afterwards, I get “ERROR: “gpio_to_irq” [drivers/power/sbs-battery.ko] undefined!
ERROR: “gpio_to_irq” [drivers/leds/trigger/ledtrig-gpio.ko] undefined!
ERROR: “gpio_to_irq” [drivers/input/touchscreen/eeti_ts.ko] undefined!”
I’ve tried editting around the various gpio header files to make sure it is actually defined in the relevant tangox headers, but that didn’t solve squat. Any idea what I’m missing? Is it just something stupid like I missed that these aren’t including the tangox/any gpio headers that are relevant?
Thanks in advance!
There seems to be some header glue I’ve overlooked. Until I get around to fixing it, just disable those modules. They won’t be of any use on this hardware anyway.
Thanks for the quick reply! Disabled those, the rest of the modules are built just fine. I’m actually trying to compile this for the Sony Dash, which uses the SMP8652. I’m expecting nothing to work given it’s 24Kf and not 74Kf, but figured this was the closest kernel to it beyond the ancient 220.127.116.11 kernel provided.
Most things should work just fine, actually, though you’ll be missing some features, e.g. PCI. All the core functionality on those chips is the same.
I found where the syscall table is on the Sony dash, so I could reuse your kexec module hack (device_shutdown omitted for now), and putting in my syscall table address for the kexec_load interception. Built the newest kexec-tools with an older glibc for the dash successfully as well. However, trying to actually kexec to my new kernel gives me
“Base address: 0x1654150 is not page aligned”
I’m missing something and I don’t quite know what. Have I just configured the new kernel wrong? And have you seen anything similar when you were compiling for the C200?