spu_run(2)

✨ spu_run(2) ✨ β€” bestie edition

okay so this is the manual page for spu_run β€” the system call that goes "run my SPU context bestie" πŸ’… it lives in the System Calls Manual, and it is so niche and so iconic. buckle up πŸŽ€


🌸 NAME 🌸

spu_run β€” execute an SPU context

πŸ“š LIBRARY πŸ“š

Standard C library (libc, -lc)


✨ SYNOPSIS ✨

#include <sys/spu.h>          /* Definition of SPU_* constants */
#include <sys/syscall.h>      /* Definition of SYS_* constants */
#include <unistd.h>

int syscall(SYS_spu_run, int fd, uint32_t *npc, uint32_t *event);
🫢 heads up bestie: glibc gives you no wrapper for spu_run(), so you have to go through syscall(2). no shortcuts, no cute little libc function, just you and the raw syscall, iykyk 😭

πŸ’– DESCRIPTION πŸ’–

The spu_run() system call is the moment ✨ it's used on PowerPC machines that implement the Cell Broadband Engine Architecture, and its whole job is letting you access Synergistic Processor Units (SPUs).

The fd argument is a file descriptor that came back from spu_create(2) and it refers to one specific SPU context. The second that context gets scheduled onto a physical SPU, it starts executing at the instruction pointer you passed in npc. main character entry point, honestly πŸ‘‘

Execution of SPU code happens synchronously β€” which is a fancy way of saying spu_run() blocks while the SPU is still running. so it's giving "wait for me" energy πŸ₯Ί If you need to run SPU code in parallel with other code on the main CPU or on other SPUs, you have to spin up a whole new thread of execution first (like, with pthread_create(3), bestie). no sharing the vibe, sorry.

When spu_run() returns, the current value of the SPU program counter gets written to npc, so you can call spu_run() again and again reusing the same npc pointer. iconic recycling behavior ♻️

The event argument is a buffer for an extended status code. If the SPU context was created with the SPU_CREATE_EVENTS_ENABLED flag, then the Linux kernel fills this buffer in before spu_run() returns. she's got receipts πŸ“

The status code can be one (or more) of these constants:

  • SPE_EVENT_DMA_ALIGNMENT β€” a DMA alignment error occurred πŸ™ˆ
  • SPE_EVENT_INVALID_DMA β€” someone tried an invalid MFC DMA command 😬
  • SPE_EVENT_SPE_DATA_STORAGE β€” a DMA storage error occurred πŸ’€
  • SPE_EVENT_SPE_ERROR β€” an illegal instruction was executed 🚨

NULL is a totally valid value for the event argument. In that case, the events just… don't get reported to the calling process. out of sight, out of mind 🌈


🫢 RETURN VALUE 🫢

On success, spu_run() returns the value of the spu_status register. On failure, it returns -1 and errno is set to indicate the error. (yes the original literally says "sets errno is set" β€” we love a typo moment, no notes πŸ’…)

The spu_status register value is a bit mask of status codes, and optionally a 14-bit code returned from the stop-and-signal instruction on the SPU. The bit masks for the status codes are:

  • 0x02 β€” SPU was stopped by a stop-and-signal instruction.
  • 0x04 β€” SPU was stopped by a halt instruction.
  • 0x08 β€” SPU is waiting for a channel.
  • 0x10 β€” SPU is in single-step mode.
  • 0x20 β€” SPU has tried to execute an invalid instruction.
  • 0x40 β€” SPU has tried to access an invalid channel.
  • 0x3fff0000 β€” the bits masked with this value contain the code returned from a stop-and-signal instruction. These bits are valid only if the 0x02 bit is set. ⚠️ (like, if 0x02 isn't set, do not trust them, periodt)

If spu_run() has not returned an error, one or more bits among the lower eight ones are always set. always always. 🌟


😭 ERRORS 😭

  • EBADF β€” fd is not a valid file descriptor.
  • EFAULT β€” npc is not a valid pointer, or event is non-NULL and an invalid pointer.
  • EINTR β€” a signal occurred while spu_run() was in progress; see signal(7). The npc value has been updated to the new program counter value if necessary. (at least she tells you where you got to πŸ₯²)
  • EINVAL β€” fd is not a valid file descriptor returned from spu_create(2).
  • ENOMEM β€” there was not enough memory available to handle a page fault resulting from a Memory Flow Controller (MFC) direct memory access.
  • ENOSYS β€” the functionality is not provided by the current system, because either the hardware does not provide SPUs or the spufs module is not loaded. no SPU bestie, no service πŸ’€

πŸ‘‘ STANDARDS πŸ‘‘

Linux on PowerPC.

πŸ¦‹ HISTORY πŸ¦‹

Linux 2.6.16.


πŸ’œ NOTES πŸ’œ

spu_run() is meant to be used from libraries that implement a more abstract interface to SPUs β€” not from regular applications, bestie. it's a "leave it to the professionals" situation fr fr. See http://www.bsc.es/projects/deepcomputing/linuxoncell/ for the recommended libraries. πŸŽ€


🌈 EXAMPLES 🌈

The following is an example of running a simple, one-instruction SPU program with the spu_run() system call. (one single instruction, and she's slaying 🌟)

#include <err.h>
#include <fcntl.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>

int main(void)
{
    int       context, fd, spu_status;
    uint32_t  instruction, npc;

    context = syscall(SYS_spu_create, "/spu/example-context", 0, 0755);
    if (context == -1)
        err(EXIT_FAILURE, "spu_create");

    /*
     * Write a 'stop 0x1234' instruction to the SPU's
     * local store memory.
     */
    instruction = 0x00001234;

    fd = open("/spu/example-context/mem", O_RDWR);
    if (fd == -1)
        err(EXIT_FAILURE, "open");
    write(fd, &instruction, sizeof(instruction));

    /*
     * set npc to the starting instruction address of the
     * SPU program.  Since we wrote the instruction at the
     * start of the mem file, the entry point will be 0x0.
     */
    npc = 0;

    spu_status = syscall(SYS_spu_run, context, &npc, NULL);
    if (spu_status == -1)
        err(EXIT_FAILURE, "open");

    /*
     * We should see a status code of 0x12340002:
     *   0x00000002 (spu was stopped due to stop-and-signal)
     * | 0x12340000 (the stop-and-signal code)
     */
    printf("SPU Status: %#08x\n", spu_status);

    exit(EXIT_SUCCESS);
}

🧚 SEE ALSO 🧚

close(2), spu_create(2), capabilities(7), spufs(7)


and that's the whole page, bestie πŸ’– this one came from the Linux man-pages 6.20, dated 2026-02-08, and it's the spu_run(2) page. go run an SPU, or don't, but either way you understood the assignment 🫢✨

πŸ“¦ where this page comes from
  • arch rolling: man-pages 6.20-1 Β· BSD-2-Clause AND BSD-3-Clause AND BSD-4.3TAHOE AND BSD-4-Clause-UC AND GPL-1.0-or-later AND GPL-2.0-only AND GPL-2.0-or-later AND GPL-3.0-or-later AND LGPL-3.0-linking-exception AND LGPL-3.0-or-later AND LicenseRef-Public-Domain AND LicenseRef-UltraPermissive AND Linux-man-pages-1-para AND Linux-man-pages-copyleft AND Linux-man-pages-copyleft-2-para AND Linux-man-pages-copyleft-var AND MIT AND Spencer-94
  • nixpkgs unstable: man-pages 6.20
  • πŸ“œ the page's license: GPL-2.0-or-later
  • πŸ’– girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms