[Cbe-oss-dev] PPE-assisted system calls

Cédric Augonnet cedric.augonnet at gmail.com
Thu May 31 16:32:02 EST 2007


2007/5/28, Julio M. Merino Vidal <jmerino at ac.upc.edu>:
> On 28/05/2007, at 5:41, Jeremy Kerr wrote:
>
> > Hi all,
> >
> >> From spufs_spu_run():
> >
> >       if ((status & SPU_STATUS_STOPPED_BY_STOP) &&
> >           (status >> SPU_STOP_STATUS_SHIFT == 0x2104)) {
> >               ret = spu_process_callback(ctx);
> >
> >
> > - this would imply that the 0x2104 stopcode is used for PPE-assisted
> > system calls.
> [...]
> > Now, I would have guessed that the term "Operating-System-Depenent
> > system calls" describes this functionality pretty well, so should
> > Linux
> > be checking for 0x2103 instead? (Or should the document be changed
> > instead? maybe people are already using 0x2104 in their apps...)
>
> By the way, is it there any example code that shows how to use
> 0x2104?  Some time ago I was inspecting the spufs and found this
> exact same bit of code, which I found very interesting.  However, I
> did some simple tests and couldn't get it to work...
>
> --
> Julio M. Merino Vidal <jmerino at ac.upc.edu>
>

If you understood how those syscalls are initiated from the SPU :
First you need to remember how the arguments of that syscall are
passed to the PPU : you have a syscall number and an array of 6
possible arguments (if your syscall requires 3 arguments, ignore the
last 3 for instance). The address of that structure containing the
arguments is transmitted throught the next program counter (npc
field). Likewise, we receive the result in the same structure :

struct spu_syscall_block {
        uint64_t nr_ret;
        uint64_t parm[6];
};

union spu_syscall_union {
   struct spu_syscall_block     args;
   uint64_t                     ret;
};

First please not that this code assumes that somehow, you put the
result of spe_ls_area_get for that thread into the __base value.

For a read sytem call, here his what you could do :

static union spu_syscall_union  sysunion;
extern uint64_t __base;

#define _NR_read        3

#define SYSCALL(sysunion)               \
    asm __volatile__(                   \
         "stop 0x2104           \n\t"   \
         ".long %0              \n\t"   \
         :"=m" (sysunion)               \
         :"m" (sysunion));

unsigned long long ppu_syscall3(unsigned long long nr,
                                unsigned long long arg1,
                                unsigned long long arg2,
                                unsigned long long arg3)
{
        sysunion.args = (struct spu_syscall_block) {
                .nr_ret = nr,
                .parm = {
                        arg1,
                        arg2,
                        arg3
                },
        };
        SYSCALL(sysunion);
        return sysunion.ret;
}

ssize_t spu_read(int fd, void *buf, size_t count)
{
    return((ssize_t)ppu_syscall3(_NR_read, fd, (uint32_t)buf + __base, count))
}

Please note that with that asm macro, we need to have the sysunion
structure static (indeed the value of its adress seems to be written
at compile time).

If anyone that has some skill in assembly could propose an improvement
to the asm macro i'd be glad to hear about it though ...

Regards,

Cédric



More information about the cbe-oss-dev mailing list