#include <pthread.h>
#include "libspe2-types.h"
Go to the source code of this file.
Data Structures | |
struct | spe_context_base_priv |
struct | spe_gang_context_base_priv |
Defines | |
#define | __PRINTF(fmt, args...) { fprintf(stderr,fmt , ## args); } |
#define | DEBUG_PRINTF(fmt, args...) |
#define | LS_SIZE 0x40000 |
#define | PSMAP_SIZE 0x20000 |
#define | MFC_SIZE 0x1000 |
#define | MSS_SIZE 0x1000 |
#define | CNTL_SIZE 0x1000 |
#define | SIGNAL_SIZE 0x1000 |
#define | MSSYNC_OFFSET 0x00000 |
#define | MFC_OFFSET 0x03000 |
#define | CNTL_OFFSET 0x04000 |
#define | SIGNAL1_OFFSET 0x14000 |
#define | SIGNAL2_OFFSET 0x1c000 |
#define | SPE_EMULATE_PARAM_BUFFER 0x3e000 |
#define | SPE_PROGRAM_NORMAL_END 0x2000 |
#define | SPE_PROGRAM_LIBRARY_CALL 0x2100 |
#define | SPE_PROGRAM_ISOLATED_STOP 0x2200 |
#define | SPE_PROGRAM_ISO_LOAD_COMPLETE 0x2206 |
Enumerations | |
enum | fd_name { FD_MBOX, FD_MBOX_STAT, FD_IBOX, FD_IBOX_NB, FD_IBOX_STAT, FD_WBOX, FD_WBOX_NB, FD_WBOX_STAT, FD_SIG1, FD_SIG2, FD_MFC, FD_MSS, NUM_MBOX_FDS } |
Functions | |
spe_context_ptr_t | _base_spe_context_create (unsigned int flags, spe_gang_context_ptr_t gctx, spe_context_ptr_t aff_spe) |
spe_gang_context_ptr_t | _base_spe_gang_context_create (unsigned int flags) |
int | _base_spe_program_load (spe_context_ptr_t spectx, spe_program_handle_t *program) |
void | _base_spe_program_load_complete (spe_context_ptr_t spectx) |
int | _base_spe_emulated_loader_present (void) |
int | _base_spe_context_destroy (spe_context_ptr_t spectx) |
int | _base_spe_gang_context_destroy (spe_gang_context_ptr_t gctx) |
int | _base_spe_context_run (spe_context_ptr_t spe, unsigned int *entry, unsigned int runflags, void *argp, void *envp, spe_stop_info_t *stopinfo) |
int | _base_spe_image_close (spe_program_handle_t *handle) |
spe_program_handle_t * | _base_spe_image_open (const char *filename) |
int | _base_spe_mfcio_put (spe_context_ptr_t spectx, unsigned int ls, void *ea, unsigned int size, unsigned int tag, unsigned int tid, unsigned int rid) |
int | _base_spe_mfcio_putb (spe_context_ptr_t spectx, unsigned int ls, void *ea, unsigned int size, unsigned int tag, unsigned int tid, unsigned int rid) |
int | _base_spe_mfcio_putf (spe_context_ptr_t spectx, unsigned int ls, void *ea, unsigned int size, unsigned int tag, unsigned int tid, unsigned int rid) |
int | _base_spe_mfcio_get (spe_context_ptr_t spectx, unsigned int ls, void *ea, unsigned int size, unsigned int tag, unsigned int tid, unsigned int rid) |
int | _base_spe_mfcio_getb (spe_context_ptr_t spectx, unsigned int ls, void *ea, unsigned int size, unsigned int tag, unsigned int tid, unsigned int rid) |
int | _base_spe_mfcio_getf (spe_context_ptr_t spectx, unsigned int ls, void *ea, unsigned int size, unsigned int tag, unsigned int tid, unsigned int rid) |
int | _base_spe_out_mbox_read (spe_context_ptr_t spectx, unsigned int mbox_data[], int count) |
int | _base_spe_in_mbox_write (spe_context_ptr_t spectx, unsigned int mbox_data[], int count, int behavior_flag) |
int | _base_spe_in_mbox_status (spe_context_ptr_t spectx) |
int | _base_spe_out_mbox_status (spe_context_ptr_t spectx) |
int | _base_spe_out_intr_mbox_status (spe_context_ptr_t spectx) |
int | _base_spe_out_intr_mbox_read (spe_context_ptr_t spectx, unsigned int mbox_data[], int count, int behavior_flag) |
int | _base_spe_signal_write (spe_context_ptr_t spectx, unsigned int signal_reg, unsigned int data) |
int | _base_spe_callback_handler_register (void *handler, unsigned int callnum, unsigned int mode) |
int | _base_spe_callback_handler_deregister (unsigned int callnum) |
void * | _base_spe_callback_handler_query (unsigned int callnum) |
int | _base_spe_stop_reason_get (spe_context_ptr_t spectx) |
int | _base_spe_mfcio_tag_status_read (spe_context_ptr_t spectx, unsigned int mask, unsigned int behavior, unsigned int *tag_status) |
int | __base_spe_stop_event_source_get (spe_context_ptr_t spectx) |
int | __base_spe_stop_event_target_get (spe_context_ptr_t spectx) |
int | _base_spe_stop_status_get (spe_context_ptr_t spectx) |
int | __base_spe_event_source_acquire (struct spe_context *spectx, enum fd_name fdesc) |
void | __base_spe_event_source_release (struct spe_context *spectx, enum fd_name fdesc) |
void * | _base_spe_ps_area_get (struct spe_context *spectx, enum ps_area area) |
int | __base_spe_spe_dir_get (struct spe_context *spectx) |
void * | _base_spe_ls_area_get (struct spe_context *spectx) |
int | _base_spe_ls_size_get (spe_context_ptr_t spe) |
void | _base_spe_context_lock (spe_context_ptr_t spe, enum fd_name fd) |
void | _base_spe_context_unlock (spe_context_ptr_t spe, enum fd_name fd) |
int | _base_spe_cpu_info_get (int info_requested, int cpu_node) |
void | __spe_context_update_event (void) |
int | _base_spe_mssync_start (spe_context_ptr_t spectx) |
int | _base_spe_mssync_status (spe_context_ptr_t spectx) |
spebase.h contains the public API funtions
Definition in file spebase.h.
#define __PRINTF | ( | fmt, | |||
args... | ) | { fprintf(stderr,fmt , ## args); } |
#define CNTL_OFFSET 0x04000 |
Definition at line 124 of file spebase.h.
Referenced by _base_spe_context_create().
#define CNTL_SIZE 0x1000 |
Definition at line 119 of file spebase.h.
Referenced by _base_spe_context_create().
#define MFC_OFFSET 0x03000 |
Definition at line 123 of file spebase.h.
Referenced by _base_spe_context_create().
#define MFC_SIZE 0x1000 |
Definition at line 117 of file spebase.h.
Referenced by _base_spe_context_create().
#define MSS_SIZE 0x1000 |
Definition at line 118 of file spebase.h.
Referenced by _base_spe_context_create().
#define MSSYNC_OFFSET 0x00000 |
Definition at line 122 of file spebase.h.
Referenced by _base_spe_context_create().
#define PSMAP_SIZE 0x20000 |
Definition at line 116 of file spebase.h.
Referenced by _base_spe_context_create().
#define SIGNAL1_OFFSET 0x14000 |
Definition at line 125 of file spebase.h.
Referenced by _base_spe_context_create().
#define SIGNAL2_OFFSET 0x1c000 |
Definition at line 126 of file spebase.h.
Referenced by _base_spe_context_create().
#define SIGNAL_SIZE 0x1000 |
Definition at line 120 of file spebase.h.
Referenced by _base_spe_context_create().
#define SPE_EMULATE_PARAM_BUFFER 0x3e000 |
Location of the PPE-assisted library call buffer for emulated isolation contexts.
Definition at line 132 of file spebase.h.
Referenced by _base_spe_handle_library_callback().
#define SPE_PROGRAM_ISO_LOAD_COMPLETE 0x2206 |
Definition at line 143 of file spebase.h.
Referenced by _base_spe_context_run().
#define SPE_PROGRAM_ISOLATED_STOP 0x2200 |
Isolated exit codes: 0x220x
Definition at line 142 of file spebase.h.
Referenced by _base_spe_context_run().
#define SPE_PROGRAM_LIBRARY_CALL 0x2100 |
Definition at line 137 of file spebase.h.
Referenced by _base_spe_context_run().
#define SPE_PROGRAM_NORMAL_END 0x2000 |
Definition at line 136 of file spebase.h.
Referenced by _base_spe_context_run().
enum fd_name |
NOTE: NUM_MBOX_FDS must always be the last element in the enumeration
FD_MBOX | |
FD_MBOX_STAT | |
FD_IBOX | |
FD_IBOX_NB | |
FD_IBOX_STAT | |
FD_WBOX | |
FD_WBOX_NB | |
FD_WBOX_STAT | |
FD_SIG1 | |
FD_SIG2 | |
FD_MFC | |
FD_MSS | |
NUM_MBOX_FDS |
Definition at line 42 of file spebase.h.
00042 { 00043 FD_MBOX, 00044 FD_MBOX_STAT, 00045 FD_IBOX, 00046 FD_IBOX_NB, 00047 FD_IBOX_STAT, 00048 FD_WBOX, 00049 FD_WBOX_NB, 00050 FD_WBOX_STAT, 00051 FD_SIG1, 00052 FD_SIG2, 00053 FD_MFC, 00054 FD_MSS, 00055 NUM_MBOX_FDS 00056 };
int __base_spe_event_source_acquire | ( | struct spe_context * | spectx, | |
enum fd_name | fdesc | |||
) |
__base_spe_event_source_acquire opens a file descriptor to the specified event source
spectx | Specifies the SPE context | |
fdesc | Specifies the event source |
void __base_spe_event_source_release | ( | struct spe_context * | spectx, | |
enum fd_name | fdesc | |||
) |
__base_spe_event_source_release releases the file descriptor to the specified event source
spectx | Specifies the SPE context | |
fdesc | Specifies the event source |
Definition at line 79 of file accessors.c.
References _base_spe_close_if_open().
00080 { 00081 _base_spe_close_if_open(spe, fdesc); 00082 }
int __base_spe_spe_dir_get | ( | struct spe_context * | spectx | ) |
__base_spe_spe_dir_get return the file descriptor of the SPE directory in spufs
spectx | Specifies the SPE context |
int __base_spe_stop_event_source_get | ( | spe_context_ptr_t | spe | ) |
__base_spe_stop_event_source_get
spectx | Specifies the SPE context |
speevent users read from this end
Definition at line 92 of file accessors.c.
References spe_context::base_private, and spe_context_base_priv::ev_pipe.
00093 { 00094 return spe->base_private->ev_pipe[1]; 00095 }
int __base_spe_stop_event_target_get | ( | spe_context_ptr_t | spe | ) |
__base_spe_stop_event_target_get
spectx | Specifies the SPE context |
speevent writes to this end
Definition at line 100 of file accessors.c.
References spe_context::base_private, and spe_context_base_priv::ev_pipe.
00101 { 00102 return spe->base_private->ev_pipe[0]; 00103 }
void __spe_context_update_event | ( | void | ) |
__spe_context_update_event internal function for gdb notification.
Referenced by _base_spe_context_destroy(), and _base_spe_program_load_complete().
int _base_spe_callback_handler_deregister | ( | unsigned int | callnum | ) |
unregister a handler function for the specified number NOTE: unregistering a handler from call zero and one is ignored.
Definition at line 78 of file lib_builtin.c.
References MAX_CALLNUM, and RESERVED.
00079 { 00080 errno = 0; 00081 if (callnum > MAX_CALLNUM) { 00082 errno = EINVAL; 00083 return -1; 00084 } 00085 if (callnum < RESERVED) { 00086 errno = EACCES; 00087 return -1; 00088 } 00089 if (handlers[callnum] == NULL) { 00090 errno = ESRCH; 00091 return -1; 00092 } 00093 00094 handlers[callnum] = NULL; 00095 return 0; 00096 }
void* _base_spe_callback_handler_query | ( | unsigned int | callnum | ) |
query a handler function for the specified number
Definition at line 98 of file lib_builtin.c.
References MAX_CALLNUM.
00099 { 00100 errno = 0; 00101 00102 if (callnum > MAX_CALLNUM) { 00103 errno = EINVAL; 00104 return NULL; 00105 } 00106 if (handlers[callnum] == NULL) { 00107 errno = ESRCH; 00108 return NULL; 00109 } 00110 return handlers[callnum]; 00111 }
int _base_spe_callback_handler_register | ( | void * | handler, | |
unsigned int | callnum, | |||
unsigned int | mode | |||
) |
register a handler function for the specified number NOTE: registering a handler to call zero and one is ignored.
Definition at line 40 of file lib_builtin.c.
References MAX_CALLNUM, RESERVED, SPE_CALLBACK_NEW, and SPE_CALLBACK_UPDATE.
00041 { 00042 errno = 0; 00043 00044 if (callnum > MAX_CALLNUM) { 00045 errno = EINVAL; 00046 return -1; 00047 } 00048 00049 switch(mode){ 00050 case SPE_CALLBACK_NEW: 00051 if (callnum < RESERVED) { 00052 errno = EACCES; 00053 return -1; 00054 } 00055 if (handlers[callnum] != NULL) { 00056 errno = EACCES; 00057 return -1; 00058 } 00059 handlers[callnum] = handler; 00060 break; 00061 00062 case SPE_CALLBACK_UPDATE: 00063 if (handlers[callnum] == NULL) { 00064 errno = ESRCH; 00065 return -1; 00066 } 00067 handlers[callnum] = handler; 00068 break; 00069 default: 00070 errno = EINVAL; 00071 return -1; 00072 break; 00073 } 00074 return 0; 00075 00076 }
spe_context_ptr_t _base_spe_context_create | ( | unsigned int | flags, | |
spe_gang_context_ptr_t | gctx, | |||
spe_context_ptr_t | aff_spe | |||
) |
_base_spe_context_create creates a single SPE context, i.e., the corresponding directory is created in SPUFS either as a subdirectory of a gang or individually (maybe this is best considered a gang of one)
flags | ||
gctx | specify NULL if not belonging to a gang | |
aff_spe | specify NULL to skip affinity information |
Definition at line 183 of file create.c.
References _base_spe_emulated_loader_present(), spe_gang_context::base_private, spe_context::base_private, spe_context_base_priv::cntl_mmap_base, CNTL_OFFSET, CNTL_SIZE, DEBUG_PRINTF, spe_context_base_priv::fd_lock, spe_context_base_priv::fd_spe_dir, spe_context_base_priv::flags, spe_gang_context_base_priv::gangname, spe_context_base_priv::loaded_program, LS_SIZE, spe_context_base_priv::mem_mmap_base, spe_context_base_priv::mfc_mmap_base, MFC_OFFSET, MFC_SIZE, MSS_SIZE, spe_context_base_priv::mssync_mmap_base, MSSYNC_OFFSET, spe_context_base_priv::psmap_mmap_base, PSMAP_SIZE, spe_context_base_priv::signal1_mmap_base, SIGNAL1_OFFSET, spe_context_base_priv::signal2_mmap_base, SIGNAL2_OFFSET, SIGNAL_SIZE, SPE_AFFINITY_MEMORY, SPE_CFG_SIGNOTIFY1_OR, SPE_CFG_SIGNOTIFY2_OR, SPE_EVENTS_ENABLE, spe_context_base_priv::spe_fds_array, SPE_ISOLATE, SPE_ISOLATE_EMULATE, and SPE_MAP_PS.
00185 { 00186 char pathname[256]; 00187 int i, aff_spe_fd = 0; 00188 unsigned int spu_createflags = 0; 00189 struct spe_context *spe = NULL; 00190 struct spe_context_base_priv *priv; 00191 00192 /* We need a loader present to run in emulated isolated mode */ 00193 if (flags & SPE_ISOLATE_EMULATE 00194 && !_base_spe_emulated_loader_present()) { 00195 errno = EINVAL; 00196 return NULL; 00197 } 00198 00199 /* Put some sane defaults into the SPE context */ 00200 spe = malloc(sizeof(*spe)); 00201 if (!spe) { 00202 DEBUG_PRINTF("ERROR: Could not allocate spe context.\n"); 00203 return NULL; 00204 } 00205 memset(spe, 0, sizeof(*spe)); 00206 00207 spe->base_private = malloc(sizeof(*spe->base_private)); 00208 if (!spe->base_private) { 00209 DEBUG_PRINTF("ERROR: Could not allocate " 00210 "spe->base_private context.\n"); 00211 free(spe); 00212 return NULL; 00213 } 00214 00215 /* just a convenience variable */ 00216 priv = spe->base_private; 00217 00218 priv->fd_spe_dir = -1; 00219 priv->mem_mmap_base = MAP_FAILED; 00220 priv->psmap_mmap_base = MAP_FAILED; 00221 priv->mssync_mmap_base = MAP_FAILED; 00222 priv->mfc_mmap_base = MAP_FAILED; 00223 priv->cntl_mmap_base = MAP_FAILED; 00224 priv->signal1_mmap_base = MAP_FAILED; 00225 priv->signal2_mmap_base = MAP_FAILED; 00226 priv->loaded_program = NULL; 00227 00228 for (i = 0; i < NUM_MBOX_FDS; i++) { 00229 priv->spe_fds_array[i] = -1; 00230 pthread_mutex_init(&priv->fd_lock[i], NULL); 00231 } 00232 00233 /* initialise spu_createflags */ 00234 if (flags & SPE_ISOLATE) { 00235 flags |= SPE_MAP_PS; 00236 spu_createflags |= SPU_CREATE_ISOLATE | SPU_CREATE_NOSCHED; 00237 } 00238 00239 if (flags & SPE_EVENTS_ENABLE) 00240 spu_createflags |= SPU_CREATE_EVENTS_ENABLED; 00241 00242 if (aff_spe) 00243 spu_createflags |= SPU_CREATE_AFFINITY_SPU; 00244 00245 if (flags & SPE_AFFINITY_MEMORY) 00246 spu_createflags |= SPU_CREATE_AFFINITY_MEM; 00247 00248 /* Make the SPUFS directory for the SPE */ 00249 if (gctx == NULL) 00250 sprintf(pathname, "/spu/spethread-%i-%lu", 00251 getpid(), (unsigned long)spe); 00252 else 00253 sprintf(pathname, "/spu/%s/spethread-%i-%lu", 00254 gctx->base_private->gangname, getpid(), 00255 (unsigned long)spe); 00256 00257 if (aff_spe) 00258 aff_spe_fd = aff_spe->base_private->fd_spe_dir; 00259 00260 priv->fd_spe_dir = spu_create(pathname, spu_createflags, 00261 S_IRUSR | S_IWUSR | S_IXUSR, aff_spe_fd); 00262 00263 if (priv->fd_spe_dir < 0) { 00264 int errno_saved = errno; /* save errno to prevent being overwritten */ 00265 DEBUG_PRINTF("ERROR: Could not create SPE %s\n", pathname); 00266 perror("spu_create()"); 00267 free_spe_context(spe); 00268 /* we mask most errors, but leave ENODEV, etc */ 00269 switch (errno_saved) { 00270 case ENOTSUP: 00271 case EEXIST: 00272 case EINVAL: 00273 case EBUSY: 00274 case EPERM: 00275 case ENODEV: 00276 errno = errno_saved; /* restore errno */ 00277 break; 00278 default: 00279 errno = EFAULT; 00280 break; 00281 } 00282 return NULL; 00283 } 00284 00285 priv->flags = flags; 00286 00287 /* Map the required areas into process memory */ 00288 priv->mem_mmap_base = mapfileat(priv->fd_spe_dir, "mem", LS_SIZE); 00289 if (priv->mem_mmap_base == MAP_FAILED) { 00290 DEBUG_PRINTF("ERROR: Could not map SPE memory.\n"); 00291 free_spe_context(spe); 00292 errno = ENOMEM; 00293 return NULL; 00294 } 00295 00296 if (flags & SPE_MAP_PS) { 00297 /* It's possible to map the entire problem state area with 00298 * one mmap - try this first */ 00299 priv->psmap_mmap_base = mapfileat(priv->fd_spe_dir, 00300 "psmap", PSMAP_SIZE); 00301 00302 if (priv->psmap_mmap_base != MAP_FAILED) { 00303 priv->mssync_mmap_base = 00304 priv->psmap_mmap_base + MSSYNC_OFFSET; 00305 priv->mfc_mmap_base = 00306 priv->psmap_mmap_base + MFC_OFFSET; 00307 priv->cntl_mmap_base = 00308 priv->psmap_mmap_base + CNTL_OFFSET; 00309 priv->signal1_mmap_base = 00310 priv->psmap_mmap_base + SIGNAL1_OFFSET; 00311 priv->signal2_mmap_base = 00312 priv->psmap_mmap_base + SIGNAL2_OFFSET; 00313 00314 } else { 00315 /* map each region separately */ 00316 priv->mfc_mmap_base = 00317 mapfileat(priv->fd_spe_dir, "mfc", MFC_SIZE); 00318 priv->mssync_mmap_base = 00319 mapfileat(priv->fd_spe_dir, "mss", MSS_SIZE); 00320 priv->cntl_mmap_base = 00321 mapfileat(priv->fd_spe_dir, "cntl", CNTL_SIZE); 00322 priv->signal1_mmap_base = 00323 mapfileat(priv->fd_spe_dir, "signal1", 00324 SIGNAL_SIZE); 00325 priv->signal2_mmap_base = 00326 mapfileat(priv->fd_spe_dir, "signal2", 00327 SIGNAL_SIZE); 00328 00329 if (priv->mfc_mmap_base == MAP_FAILED || 00330 priv->cntl_mmap_base == MAP_FAILED || 00331 priv->signal1_mmap_base == MAP_FAILED || 00332 priv->signal2_mmap_base == MAP_FAILED) { 00333 DEBUG_PRINTF("ERROR: Could not map SPE " 00334 "PS memory.\n"); 00335 free_spe_context(spe); 00336 errno = ENOMEM; 00337 return NULL; 00338 } 00339 } 00340 } 00341 00342 if (flags & SPE_CFG_SIGNOTIFY1_OR) { 00343 if (setsignotify(priv->fd_spe_dir, "signal1_type")) { 00344 DEBUG_PRINTF("ERROR: Could not open SPE " 00345 "signal1_type file.\n"); 00346 free_spe_context(spe); 00347 errno = EFAULT; 00348 return NULL; 00349 } 00350 } 00351 00352 if (flags & SPE_CFG_SIGNOTIFY2_OR) { 00353 if (setsignotify(priv->fd_spe_dir, "signal2_type")) { 00354 DEBUG_PRINTF("ERROR: Could not open SPE " 00355 "signal2_type file.\n"); 00356 free_spe_context(spe); 00357 errno = EFAULT; 00358 return NULL; 00359 } 00360 } 00361 00362 return spe; 00363 }
int _base_spe_context_destroy | ( | spe_context_ptr_t | spectx | ) |
_base_spe_context_destroy cleans up what is left when an SPE executable has exited. Closes open file handles and unmaps memory areas.
spectx | Specifies the SPE context |
Definition at line 418 of file create.c.
References __spe_context_update_event().
00419 { 00420 int ret = free_spe_context(spe); 00421 00422 __spe_context_update_event(); 00423 00424 return ret; 00425 }
void _base_spe_context_lock | ( | spe_context_ptr_t | spe, | |
enum fd_name | fd | |||
) |
_base_spe_context_lock locks members of the SPE context
spectx | Specifies the SPE context | |
fd | Specifies the file |
Definition at line 91 of file create.c.
References spe_context::base_private, and spe_context_base_priv::fd_lock.
Referenced by _base_spe_close_if_open(), and _base_spe_open_if_closed().
00092 { 00093 pthread_mutex_lock(&spe->base_private->fd_lock[fdesc]); 00094 }
int _base_spe_context_run | ( | spe_context_ptr_t | spe, | |
unsigned int * | entry, | |||
unsigned int | runflags, | |||
void * | argp, | |||
void * | envp, | |||
spe_stop_info_t * | stopinfo | |||
) |
_base_spe_context_run starts execution of an SPE context with a loaded image
spectx | Specifies the SPE context | |
entry | entry point for the SPE programm. If set to 0, entry point is determined by the ELF loader. | |
runflags | valid values are: SPE_RUN_USER_REGS Specifies that the SPE setup registers r3, r4, and r5 are initialized with the 48 bytes pointed to by argp. SPE_NO_CALLBACKS do not use built in library functions. | |
argp | An (optional) pointer to application specific data, and is passed as the second parameter to the SPE program. | |
envp | An (optional) pointer to environment specific data, and is passed as the third parameter to the SPE program. |
Definition at line 99 of file run.c.
References __spe_current_active_context, _base_spe_handle_library_callback(), _base_spe_program_load_complete(), spe_context::base_private, DEBUG_PRINTF, spe_context_base_priv::emulated_entry, spe_context_base_priv::entry, spe_context_base_priv::fd_spe_dir, spe_context_base_priv::flags, LS_SIZE, spe_context_base_priv::mem_mmap_base, spe_context_info::npc, spe_context_info::prev, spe_stop_info::result, spe_stop_info::spe_callback_error, SPE_CALLBACK_ERROR, SPE_DEFAULT_ENTRY, SPE_EVENTS_ENABLE, SPE_EXIT, spe_stop_info::spe_exit_code, spe_context_info::spe_id, SPE_ISOLATE, SPE_ISOLATE_EMULATE, spe_stop_info::spe_isolation_error, SPE_ISOLATION_ERROR, SPE_NO_CALLBACKS, SPE_PROGRAM_ISO_LOAD_COMPLETE, SPE_PROGRAM_ISOLATED_STOP, SPE_PROGRAM_LIBRARY_CALL, SPE_PROGRAM_NORMAL_END, SPE_RUN_USER_REGS, spe_stop_info::spe_runtime_error, SPE_RUNTIME_ERROR, spe_stop_info::spe_runtime_exception, SPE_RUNTIME_EXCEPTION, spe_stop_info::spe_runtime_fatal, SPE_RUNTIME_FATAL, spe_stop_info::spe_signal_code, SPE_SPU_HALT, SPE_SPU_INVALID_CHANNEL, SPE_SPU_INVALID_INSTR, SPE_SPU_STOPPED_BY_STOP, SPE_SPU_WAITING_ON_CHANNEL, SPE_STOP_AND_SIGNAL, spe_stop_info::spu_status, spe_context_info::status, spe_stop_info::stop_reason, addr64::ui, and addr64::ull.
Referenced by _event_spe_context_run().
00102 { 00103 int retval = 0, run_rc; 00104 unsigned int run_status, tmp_entry; 00105 spe_stop_info_t stopinfo_buf; 00106 struct spe_context_info this_context_info __attribute__((cleanup(cleanupspeinfo))); 00107 00108 /* If the caller hasn't set a stopinfo buffer, provide a buffer on the 00109 * stack instead. */ 00110 if (!stopinfo) 00111 stopinfo = &stopinfo_buf; 00112 00113 00114 /* In emulated isolated mode, the npc will always return as zero. 00115 * use our private entry point instead */ 00116 if (spe->base_private->flags & SPE_ISOLATE_EMULATE) 00117 tmp_entry = spe->base_private->emulated_entry; 00118 00119 else if (*entry == SPE_DEFAULT_ENTRY) 00120 tmp_entry = spe->base_private->entry; 00121 else 00122 tmp_entry = *entry; 00123 00124 /* If we're starting the SPE binary from its original entry point, 00125 * setup the arguments to main() */ 00126 if (tmp_entry == spe->base_private->entry && 00127 !(spe->base_private->flags & 00128 (SPE_ISOLATE | SPE_ISOLATE_EMULATE))) { 00129 00130 addr64 argp64, envp64, tid64, ls64; 00131 unsigned int regs[128][4]; 00132 00133 /* setup parameters */ 00134 argp64.ull = (uint64_t)(unsigned long)argp; 00135 envp64.ull = (uint64_t)(unsigned long)envp; 00136 tid64.ull = (uint64_t)(unsigned long)spe; 00137 00138 /* make sure the register values are 0 */ 00139 memset(regs, 0, sizeof(regs)); 00140 00141 /* set sensible values for stack_ptr and stack_size */ 00142 regs[1][0] = (unsigned int) LS_SIZE - 16; /* stack_ptr */ 00143 regs[2][0] = 0; /* stack_size ( 0 = default ) */ 00144 00145 if (runflags & SPE_RUN_USER_REGS) { 00146 /* When SPE_USER_REGS is set, argp points to an array 00147 * of 3x128b registers to be passed directly to the SPE 00148 * program. 00149 */ 00150 memcpy(regs[3], argp, sizeof(unsigned int) * 12); 00151 } else { 00152 regs[3][0] = tid64.ui[0]; 00153 regs[3][1] = tid64.ui[1]; 00154 00155 regs[4][0] = argp64.ui[0]; 00156 regs[4][1] = argp64.ui[1]; 00157 00158 regs[5][0] = envp64.ui[0]; 00159 regs[5][1] = envp64.ui[1]; 00160 } 00161 00162 /* Store the LS base address in R6 */ 00163 ls64.ull = (uint64_t)(unsigned long)spe->base_private->mem_mmap_base; 00164 regs[6][0] = ls64.ui[0]; 00165 regs[6][1] = ls64.ui[1]; 00166 00167 if (set_regs(spe, regs)) 00168 return -1; 00169 } 00170 00171 /*Leave a trail of breadcrumbs for the debugger to follow */ 00172 if (!__spe_current_active_context) { 00173 __spe_current_active_context = &this_context_info; 00174 if (!__spe_current_active_context) 00175 return -1; 00176 __spe_current_active_context->prev = NULL; 00177 } else { 00178 struct spe_context_info *newinfo; 00179 newinfo = &this_context_info; 00180 if (!newinfo) 00181 return -1; 00182 newinfo->prev = __spe_current_active_context; 00183 __spe_current_active_context = newinfo; 00184 } 00185 /*remember the ls-addr*/ 00186 __spe_current_active_context->spe_id = spe->base_private->fd_spe_dir; 00187 00188 do_run: 00189 /*Remember the npc value*/ 00190 __spe_current_active_context->npc = tmp_entry; 00191 00192 /* run SPE context */ 00193 run_rc = spu_run(spe->base_private->fd_spe_dir, 00194 &tmp_entry, &run_status); 00195 00196 /*Remember the npc value*/ 00197 __spe_current_active_context->npc = tmp_entry; 00198 __spe_current_active_context->status = run_status; 00199 00200 DEBUG_PRINTF("spu_run returned run_rc=0x%08x, entry=0x%04x, " 00201 "ext_status=0x%04x.\n", run_rc, tmp_entry, run_status); 00202 00203 /* set up return values and stopinfo according to spu_run exit 00204 * conditions. This is overwritten on error. 00205 */ 00206 stopinfo->spu_status = run_rc; 00207 00208 if (spe->base_private->flags & SPE_ISOLATE_EMULATE) { 00209 /* save the entry point, and pretend that the npc is zero */ 00210 spe->base_private->emulated_entry = tmp_entry; 00211 *entry = 0; 00212 } else { 00213 *entry = tmp_entry; 00214 } 00215 00216 /* Return with stopinfo set on syscall error paths */ 00217 if (run_rc == -1) { 00218 DEBUG_PRINTF("spu_run returned error %d, errno=%d\n", 00219 run_rc, errno); 00220 stopinfo->stop_reason = SPE_RUNTIME_FATAL; 00221 stopinfo->result.spe_runtime_fatal = errno; 00222 retval = -1; 00223 00224 /* For isolated contexts, pass EPERM up to the 00225 * caller. 00226 */ 00227 if (!(spe->base_private->flags & SPE_ISOLATE 00228 && errno == EPERM)) 00229 errno = EFAULT; 00230 00231 } else if (run_rc & SPE_SPU_INVALID_INSTR) { 00232 DEBUG_PRINTF("SPU has tried to execute an invalid " 00233 "instruction. %d\n", run_rc); 00234 stopinfo->stop_reason = SPE_RUNTIME_ERROR; 00235 stopinfo->result.spe_runtime_error = SPE_SPU_INVALID_INSTR; 00236 errno = EFAULT; 00237 retval = -1; 00238 00239 } else if ((spe->base_private->flags & SPE_EVENTS_ENABLE) && run_status) { 00240 /* Report asynchronous error if return val are set and 00241 * SPU events are enabled. 00242 */ 00243 stopinfo->stop_reason = SPE_RUNTIME_EXCEPTION; 00244 stopinfo->result.spe_runtime_exception = run_status; 00245 stopinfo->spu_status = -1; 00246 errno = EIO; 00247 retval = -1; 00248 00249 } else if (run_rc & SPE_SPU_STOPPED_BY_STOP) { 00250 /* Stop & signals are broken down into three groups 00251 * 1. SPE library call 00252 * 2. SPE user defined stop & signal 00253 * 3. SPE program end. 00254 * 00255 * These groups are signified by the 14-bit stop code: 00256 */ 00257 int stopcode = (run_rc >> 16) & 0x3fff; 00258 00259 /* Check if this is a library callback, and callbacks are 00260 * allowed (ie, running without SPE_NO_CALLBACKS) 00261 */ 00262 if ((stopcode & 0xff00) == SPE_PROGRAM_LIBRARY_CALL 00263 && !(runflags & SPE_NO_CALLBACKS)) { 00264 00265 int callback_rc, callback_number = stopcode & 0xff; 00266 00267 /* execute library callback */ 00268 DEBUG_PRINTF("SPE library call: %d\n", callback_number); 00269 callback_rc = _base_spe_handle_library_callback(spe, 00270 callback_number, *entry); 00271 00272 if (callback_rc) { 00273 /* library callback failed; set errno and 00274 * return immediately */ 00275 DEBUG_PRINTF("SPE library call failed: %d\n", 00276 callback_rc); 00277 stopinfo->stop_reason = SPE_CALLBACK_ERROR; 00278 stopinfo->result.spe_callback_error = 00279 callback_rc; 00280 errno = EFAULT; 00281 retval = -1; 00282 } else { 00283 /* successful library callback - restart the SPE 00284 * program at the next instruction */ 00285 tmp_entry += 4; 00286 goto do_run; 00287 } 00288 00289 } else if ((stopcode & 0xff00) == SPE_PROGRAM_NORMAL_END) { 00290 /* The SPE program has exited by exit(X) */ 00291 stopinfo->stop_reason = SPE_EXIT; 00292 stopinfo->result.spe_exit_code = stopcode & 0xff; 00293 00294 if (spe->base_private->flags & SPE_ISOLATE) { 00295 /* Issue an isolated exit, and re-run the SPE. 00296 * We should see a return value without the 00297 * 0x80 bit set. */ 00298 if (!issue_isolated_exit(spe)) 00299 goto do_run; 00300 retval = -1; 00301 } 00302 00303 } else if ((stopcode & 0xfff0) == SPE_PROGRAM_ISOLATED_STOP) { 00304 00305 /* 0x2206: isolated app has been loaded by loader; 00306 * provide a hook for the debugger to catch this, 00307 * and restart 00308 */ 00309 if (stopcode == SPE_PROGRAM_ISO_LOAD_COMPLETE) { 00310 _base_spe_program_load_complete(spe); 00311 goto do_run; 00312 } else { 00313 stopinfo->stop_reason = SPE_ISOLATION_ERROR; 00314 stopinfo->result.spe_isolation_error = 00315 stopcode & 0xf; 00316 } 00317 00318 } else if (spe->base_private->flags & SPE_ISOLATE && 00319 !(run_rc & 0x80)) { 00320 /* We've successfully exited isolated mode */ 00321 retval = 0; 00322 00323 } else { 00324 /* User defined stop & signal, including 00325 * callbacks when disabled */ 00326 stopinfo->stop_reason = SPE_STOP_AND_SIGNAL; 00327 stopinfo->result.spe_signal_code = stopcode; 00328 retval = stopcode; 00329 } 00330 00331 } else if (run_rc & SPE_SPU_HALT) { 00332 DEBUG_PRINTF("SPU was stopped by halt. %d\n", run_rc); 00333 stopinfo->stop_reason = SPE_RUNTIME_ERROR; 00334 stopinfo->result.spe_runtime_error = SPE_SPU_HALT; 00335 errno = EFAULT; 00336 retval = -1; 00337 00338 } else if (run_rc & SPE_SPU_WAITING_ON_CHANNEL) { 00339 DEBUG_PRINTF("SPU is waiting on channel. %d\n", run_rc); 00340 stopinfo->stop_reason = SPE_RUNTIME_EXCEPTION; 00341 stopinfo->result.spe_runtime_exception = run_status; 00342 stopinfo->spu_status = -1; 00343 errno = EIO; 00344 retval = -1; 00345 00346 } else if (run_rc & SPE_SPU_INVALID_CHANNEL) { 00347 DEBUG_PRINTF("SPU has tried to access an invalid " 00348 "channel. %d\n", run_rc); 00349 stopinfo->stop_reason = SPE_RUNTIME_ERROR; 00350 stopinfo->result.spe_runtime_error = SPE_SPU_INVALID_CHANNEL; 00351 errno = EFAULT; 00352 retval = -1; 00353 00354 } else { 00355 DEBUG_PRINTF("spu_run returned invalid data: 0x%04x\n", run_rc); 00356 stopinfo->stop_reason = SPE_RUNTIME_FATAL; 00357 stopinfo->result.spe_runtime_fatal = -1; 00358 stopinfo->spu_status = -1; 00359 errno = EFAULT; 00360 retval = -1; 00361 00362 } 00363 00364 freespeinfo(); 00365 return retval; 00366 }
void _base_spe_context_unlock | ( | spe_context_ptr_t | spe, | |
enum fd_name | fd | |||
) |
_base_spe_context_unlock unlocks members of the SPE context
spectx | Specifies the SPE context | |
fd | Specifies the file |
Definition at line 96 of file create.c.
References spe_context::base_private, and spe_context_base_priv::fd_lock.
Referenced by _base_spe_close_if_open(), and _base_spe_open_if_closed().
00097 { 00098 pthread_mutex_unlock(&spe->base_private->fd_lock[fdesc]); 00099 }
int _base_spe_cpu_info_get | ( | int | info_requested, | |
int | cpu_node | |||
) |
_base_spe_info_get
Definition at line 105 of file info.c.
References _base_spe_count_physical_cpus(), _base_spe_count_physical_spes(), _base_spe_count_usable_spes(), SPE_COUNT_PHYSICAL_CPU_NODES, SPE_COUNT_PHYSICAL_SPES, and SPE_COUNT_USABLE_SPES.
00105 { 00106 int ret = 0; 00107 errno = 0; 00108 00109 switch (info_requested) { 00110 case SPE_COUNT_PHYSICAL_CPU_NODES: 00111 ret = _base_spe_count_physical_cpus(cpu_node); 00112 break; 00113 case SPE_COUNT_PHYSICAL_SPES: 00114 ret = _base_spe_count_physical_spes(cpu_node); 00115 break; 00116 case SPE_COUNT_USABLE_SPES: 00117 ret = _base_spe_count_usable_spes(cpu_node); 00118 break; 00119 default: 00120 errno = EINVAL; 00121 ret = -1; 00122 } 00123 return ret; 00124 }
int _base_spe_emulated_loader_present | ( | void | ) |
Check if the emulated loader is present in the filesystem
Definition at line 159 of file load.c.
References _base_spe_verify_spe_elf_image().
Referenced by _base_spe_context_create().
00160 { 00161 spe_program_handle_t *loader = emulated_loader_program(); 00162 00163 if (!loader) 00164 return 0; 00165 00166 return !_base_spe_verify_spe_elf_image(loader); 00167 }
spe_gang_context_ptr_t _base_spe_gang_context_create | ( | unsigned int | flags | ) |
creates the directory in SPUFS that will contain all SPEs that are considered a gang Note: I would like to generalize this to a "group" or "set" Additional attributes maintained at the group level should be used to define scheduling constraints such "temporal" (e.g., scheduled all at the same time, i.e., a gang) "topology" (e.g., "closeness" of SPEs for optimal communication)
Definition at line 376 of file create.c.
References spe_gang_context::base_private, DEBUG_PRINTF, and spe_gang_context_base_priv::gangname.
00377 { 00378 char pathname[256]; 00379 struct spe_gang_context_base_priv *pgctx = NULL; 00380 struct spe_gang_context *gctx = NULL; 00381 00382 gctx = malloc(sizeof(*gctx)); 00383 if (!gctx) { 00384 DEBUG_PRINTF("ERROR: Could not allocate spe context.\n"); 00385 return NULL; 00386 } 00387 memset(gctx, 0, sizeof(*gctx)); 00388 00389 pgctx = malloc(sizeof(*pgctx)); 00390 if (!pgctx) { 00391 DEBUG_PRINTF("ERROR: Could not allocate spe context.\n"); 00392 free(gctx); 00393 return NULL; 00394 } 00395 memset(pgctx, 0, sizeof(*pgctx)); 00396 00397 gctx->base_private = pgctx; 00398 00399 sprintf(gctx->base_private->gangname, "gang-%i-%lu", getpid(), 00400 (unsigned long)gctx); 00401 sprintf(pathname, "/spu/%s", gctx->base_private->gangname); 00402 00403 gctx->base_private->fd_gang_dir = spu_create(pathname, SPU_CREATE_GANG, 00404 S_IRUSR | S_IWUSR | S_IXUSR); 00405 00406 if (gctx->base_private->fd_gang_dir < 0) { 00407 DEBUG_PRINTF("ERROR: Could not create Gang %s\n", pathname); 00408 free_spe_gang_context(gctx); 00409 errno = EFAULT; 00410 return NULL; 00411 } 00412 00413 gctx->base_private->flags = flags; 00414 00415 return gctx; 00416 }
int _base_spe_gang_context_destroy | ( | spe_gang_context_ptr_t | gctx | ) |
int _base_spe_image_close | ( | spe_program_handle_t * | handle | ) |
_base_spe_image_close unmaps an SPE ELF object that was previously mapped using spe_open_image.
handle | handle to open file |
0 | On success, spe_close_image returns 0. | |
-1 | On failure, -1 is returned and errno is set appropriately. Possible values for errno: EINVAL From spe_close_image, this indicates that the file, specified by filename, was not previously mapped by a call to spe_open_image. |
Definition at line 96 of file image.c.
References spe_program_handle::elf_image, image_handle::map_size, image_handle::speh, and spe_program_handle::toe_shadow.
00097 { 00098 int ret = 0; 00099 struct image_handle *ih; 00100 00101 if (!handle) { 00102 errno = EINVAL; 00103 return -1; 00104 } 00105 00106 ih = (struct image_handle *)handle; 00107 00108 if (!ih->speh.elf_image || !ih->map_size) { 00109 errno = EINVAL; 00110 return -1; 00111 } 00112 00113 if (ih->speh.toe_shadow) 00114 free(ih->speh.toe_shadow); 00115 00116 ret = munmap(ih->speh.elf_image, ih->map_size ); 00117 free(handle); 00118 00119 return ret; 00120 }
spe_program_handle_t* _base_spe_image_open | ( | const char * | filename | ) |
_base_spe_image_open maps an SPE ELF executable indicated by filename into system memory and returns the mapped address appropriate for use by the spe_create_thread API. It is often more convenient/appropriate to use the loading methodologies where SPE ELF objects are converted to PPE static or shared libraries with symbols which point to the SPE ELF objects after these special libraries are loaded. These libraries are then linked with the associated PPE code to provide a direct symbol reference to the SPE ELF object. The symbols in this scheme are equivalent to the address returned from the spe_open_image function. SPE ELF objects loaded using this function are not shared with other processes, but SPE ELF objects loaded using the other scheme, mentioned above, can be shared if so desired.
filename | Specifies the filename of an SPE ELF executable to be loaded and mapped into system memory. |
A number of other errno values could be returned by the open(2), fstat(2), mmap(2), munmap(2), or close(2) system calls which may be utilized by the spe_open_image or spe_close_image functions.
Definition at line 37 of file image.c.
References _base_spe_toe_ear(), _base_spe_verify_spe_elf_image(), spe_program_handle::elf_image, spe_program_handle::handle_size, image_handle::map_size, image_handle::speh, and spe_program_handle::toe_shadow.
00038 { 00039 /* allocate an extra integer in the spe handle to keep the mapped size information */ 00040 struct image_handle *ret; 00041 int binfd = -1, f_stat; 00042 struct stat statbuf; 00043 size_t ps = getpagesize (); 00044 00045 ret = malloc(sizeof(struct image_handle)); 00046 if (!ret) 00047 return NULL; 00048 00049 ret->speh.handle_size = sizeof(spe_program_handle_t); 00050 ret->speh.toe_shadow = NULL; 00051 00052 binfd = open(filename, O_RDONLY); 00053 if (binfd < 0) 00054 goto ret_err; 00055 00056 f_stat = fstat(binfd, &statbuf); 00057 if (f_stat < 0) 00058 goto ret_err; 00059 00060 /* Sanity: is it executable ? 00061 */ 00062 if(!(statbuf.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH))) { 00063 errno=EACCES; 00064 goto ret_err; 00065 } 00066 00067 /* now store the size at the extra allocated space */ 00068 ret->map_size = (statbuf.st_size + ps - 1) & ~(ps - 1); 00069 00070 ret->speh.elf_image = mmap(NULL, ret->map_size, 00071 PROT_WRITE | PROT_READ, 00072 MAP_PRIVATE, binfd, 0); 00073 if (ret->speh.elf_image == MAP_FAILED) 00074 goto ret_err; 00075 00076 /*Verify that this is a valid SPE ELF object*/ 00077 if((_base_spe_verify_spe_elf_image((spe_program_handle_t *)ret))) 00078 goto ret_err; 00079 00080 if (_base_spe_toe_ear(&ret->speh)) 00081 goto ret_err; 00082 00083 /* ok */ 00084 close(binfd); 00085 return (spe_program_handle_t *)ret; 00086 00087 /* err & cleanup */ 00088 ret_err: 00089 if (binfd >= 0) 00090 close(binfd); 00091 00092 free(ret); 00093 return NULL; 00094 }
int _base_spe_in_mbox_status | ( | spe_context_ptr_t | spectx | ) |
The _base_spe_in_mbox_status function fetches the status of the SPU inbound mailbox for the SPE thread specified by the speid parameter. A 0 value is return if the mailbox is full. A non-zero value specifies the number of available (32-bit) mailbox entries.
spectx | Specifies the SPE context whose mailbox status is to be read. |
Definition at line 202 of file mbox.c.
References _base_spe_open_if_closed(), spe_context::base_private, spe_context_base_priv::cntl_mmap_base, FD_WBOX_STAT, spe_context_base_priv::flags, SPE_MAP_PS, and spe_spu_control_area::SPU_Mbox_Stat.
00203 { 00204 int rc, ret; 00205 volatile struct spe_spu_control_area *cntl_area = 00206 spectx->base_private->cntl_mmap_base; 00207 00208 if (spectx->base_private->flags & SPE_MAP_PS) { 00209 ret = (cntl_area->SPU_Mbox_Stat >> 8) & 0xFF; 00210 } else { 00211 rc = read(_base_spe_open_if_closed(spectx,FD_WBOX_STAT, 0), &ret, 4); 00212 if (rc != 4) 00213 ret = -1; 00214 } 00215 00216 return ret; 00217 00218 }
int _base_spe_in_mbox_write | ( | spe_context_ptr_t | spectx, | |
unsigned int | mbox_data[], | |||
int | count, | |||
int | behavior_flag | |||
) |
The _base_spe_in_mbox_write function writes mbox_data to the SPE inbound mailbox for the SPE thread speid.
If the behavior flag indicates ALL_BLOCKING the call will try to write exactly count mailbox entries and block until the write request is satisfied, i.e., exactly count mailbox entries have been written. If the behavior flag indicates ANY_BLOCKING the call will try to write up to count mailbox entries, and block until the write request is satisfied, i.e., at least 1 mailbox entry has been written. If the behavior flag indicates ANY_NON_BLOCKING the call will not block until the write request is satisfied, but instead write whatever is immediately possible and return the number of mailbox entries written. spe_stat_in_mbox can be called to ensure that data can be written prior to calling the function.
spectx | Specifies the SPE thread whose outbound mailbox is to be read. | |
mbox_data | ||
count | ||
behavior_flag | ALL_BLOCKING ANY_BLOCKING ANY_NON_BLOCKING |
>=0 | the number of 32-bit mailbox messages written | |
-1 | error condition and errno is set Possible values for errno: EINVAL spectx is invalid Exxxx what else do we need here?? |
void* _base_spe_ls_area_get | ( | struct spe_context * | spectx | ) |
_base_spe_ls_area_get returns a pointer to the start of the memory mapped local store area
spectx | Specifies the SPE context |
int _base_spe_ls_size_get | ( | spe_context_ptr_t | spe | ) |
_base_spe_ls_size_get returns the size of the local store area
spectx | Specifies the SPE context |
Definition at line 105 of file accessors.c.
References LS_SIZE.
00106 { 00107 return LS_SIZE; 00108 }
int _base_spe_mfcio_get | ( | spe_context_ptr_t | spectx, | |
unsigned int | ls, | |||
void * | ea, | |||
unsigned int | size, | |||
unsigned int | tag, | |||
unsigned int | tid, | |||
unsigned int | rid | |||
) |
The _base_spe_mfcio_get function places a get DMA command on the proxy command queue of the SPE thread specified by speid. The get command transfers size bytes of data starting at the effective address specified by ea to the local store address specified by ls. The DMA is identified by the tag id specified by tag and performed according to the transfer class and replacement class specified by tid and rid respectively.
spectx | Specifies the SPE context | |
ls | Specifies the starting local store destination address. | |
ea | Specifies the starting effective address source address. | |
size | Specifies the size, in bytes, to be transferred. | |
tag | Specifies the tag id used to identify the DMA command. | |
tid | Specifies the transfer class identifier of the DMA command. | |
rid | Specifies the replacement class identifier of the DMA command. |
Definition at line 160 of file dma.c.
References MFC_CMD_GET.
00167 { 00168 return spe_do_mfc_get(spectx, ls, ea, size, tag, tid, rid, MFC_CMD_GET); 00169 }
int _base_spe_mfcio_getb | ( | spe_context_ptr_t | spectx, | |
unsigned int | ls, | |||
void * | ea, | |||
unsigned int | size, | |||
unsigned int | tag, | |||
unsigned int | tid, | |||
unsigned int | rid | |||
) |
The _base_spe_mfcio_getb function is identical to _base_spe_mfcio_get except that it places a getb (get with barrier) DMA command on the proxy command queue. The barrier form ensures that this command and all sequence commands with the same tag identifier as this command are locally ordered with respect to all previously issued commands with the same tag group and command queue.
spectx | Specifies the SPE context | |
ls | Specifies the starting local store destination address. | |
ea | Specifies the starting effective address source address. | |
size | Specifies the size, in bytes, to be transferred. | |
tag | Specifies the tag id used to identify the DMA command. | |
tid | Specifies the transfer class identifier of the DMA command. | |
rid | Specifies the replacement class identifier of the DMA command. |
Definition at line 171 of file dma.c.
References MFC_CMD_GETB.
00178 { 00179 return spe_do_mfc_get(spectx, ls, ea, size, tag, rid, rid, MFC_CMD_GETB); 00180 }
int _base_spe_mfcio_getf | ( | spe_context_ptr_t | spectx, | |
unsigned int | ls, | |||
void * | ea, | |||
unsigned int | size, | |||
unsigned int | tag, | |||
unsigned int | tid, | |||
unsigned int | rid | |||
) |
The _base_spe_mfcio_getf function is identical to _base_spe_mfcio_get except that it places a getf (get with fence) DMA command on the proxy command queue. The fence form ensure that this command is locally ordered with respect to all previously issued commands with the same tag group and command queue.
spectx | Specifies the SPE context | |
ls | Specifies the starting local store destination address. | |
ea | Specifies the starting effective address source address. | |
size | Specifies the size, in bytes, to be transferred. | |
tag | Specifies the tag id used to identify the DMA command. | |
tid | Specifies the transfer class identifier of the DMA command. | |
rid | Specifies the replacement class identifier of the DMA command. |
Definition at line 182 of file dma.c.
References MFC_CMD_GETF.
00189 { 00190 return spe_do_mfc_get(spectx, ls, ea, size, tag, tid, rid, MFC_CMD_GETF); 00191 }
int _base_spe_mfcio_put | ( | spe_context_ptr_t | spectx, | |
unsigned int | ls, | |||
void * | ea, | |||
unsigned int | size, | |||
unsigned int | tag, | |||
unsigned int | tid, | |||
unsigned int | rid | |||
) |
The _base_spe_mfcio_put function places a put DMA command on the proxy command queue of the SPE thread specified by speid. The put command transfers size bytes of data starting at the local store address specified by ls to the effective address specified by ea. The DMA is identified by the tag id specified by tag and performed according transfer class and replacement class specified by tid and rid respectively.
spectx | Specifies the SPE context | |
ls | Specifies the starting local store destination address. | |
ea | Specifies the starting effective address source address. | |
size | Specifies the size, in bytes, to be transferred. | |
tag | Specifies the tag id used to identify the DMA command. | |
tid | Specifies the transfer class identifier of the DMA command. | |
rid | Specifies the replacement class identifier of the DMA command. |
Definition at line 126 of file dma.c.
References MFC_CMD_PUT.
00133 { 00134 return spe_do_mfc_put(spectx, ls, ea, size, tag, tid, rid, MFC_CMD_PUT); 00135 }
int _base_spe_mfcio_putb | ( | spe_context_ptr_t | spectx, | |
unsigned int | ls, | |||
void * | ea, | |||
unsigned int | size, | |||
unsigned int | tag, | |||
unsigned int | tid, | |||
unsigned int | rid | |||
) |
The _base_spe_mfcio_putb function is identical to _base_spe_mfcio_put except that it places a putb (put with barrier) DMA command on the proxy command queue. The barrier form ensures that this command and all sequence commands with the same tag identifier as this command are locally ordered with respect to all previously i ssued commands with the same tag group and command queue.
spectx | Specifies the SPE context | |
ls | Specifies the starting local store destination address. | |
ea | Specifies the starting effective address source address. | |
size | Specifies the size, in bytes, to be transferred. | |
tag | Specifies the tag id used to identify the DMA command. | |
tid | Specifies the transfer class identifier of the DMA command. | |
rid | Specifies the replacement class identifier of the DMA command. |
Definition at line 137 of file dma.c.
References MFC_CMD_PUTB.
00144 { 00145 return spe_do_mfc_put(spectx, ls, ea, size, tag, tid, rid, MFC_CMD_PUTB); 00146 }
int _base_spe_mfcio_putf | ( | spe_context_ptr_t | spectx, | |
unsigned int | ls, | |||
void * | ea, | |||
unsigned int | size, | |||
unsigned int | tag, | |||
unsigned int | tid, | |||
unsigned int | rid | |||
) |
The _base_spe_mfcio_putf function is identical to _base_spe_mfcio_put except that it places a putf (put with fence) DMA command on the proxy command queue. The fence form ensures that this command is locally ordered with respect to all previously issued commands with the same tag group and command queue.
spectx | Specifies the SPE context | |
ls | Specifies the starting local store destination address. | |
ea | Specifies the starting effective address source address. | |
size | Specifies the size, in bytes, to be transferred. | |
tag | Specifies the tag id used to identify the DMA command. | |
tid | Specifies the transfer class identifier of the DMA command. | |
rid | Specifies the replacement class identifier of the DMA command. |
Definition at line 148 of file dma.c.
References MFC_CMD_PUTF.
00155 { 00156 return spe_do_mfc_put(spectx, ls, ea, size, tag, tid, rid, MFC_CMD_PUTF); 00157 }
int _base_spe_mfcio_tag_status_read | ( | spe_context_ptr_t | spectx, | |
unsigned int | mask, | |||
unsigned int | behavior, | |||
unsigned int * | tag_status | |||
) |
_base_spe_mfcio_tag_status_read
No Idea
Definition at line 307 of file dma.c.
References spe_context_base_priv::active_tagmask, spe_context::base_private, spe_context_base_priv::flags, SPE_MAP_PS, SPE_TAG_ALL, SPE_TAG_ANY, and SPE_TAG_IMMEDIATE.
00308 { 00309 if ( mask != 0 ) { 00310 if (!(spectx->base_private->flags & SPE_MAP_PS)) 00311 mask = 0; 00312 } else { 00313 if ((spectx->base_private->flags & SPE_MAP_PS)) 00314 mask = spectx->base_private->active_tagmask; 00315 } 00316 00317 if (!tag_status) { 00318 errno = EINVAL; 00319 return -1; 00320 } 00321 00322 switch (behavior) { 00323 case SPE_TAG_ALL: 00324 return spe_mfcio_tag_status_read_all(spectx, mask, tag_status); 00325 case SPE_TAG_ANY: 00326 return spe_mfcio_tag_status_read_any(spectx, mask, tag_status); 00327 case SPE_TAG_IMMEDIATE: 00328 return spe_mfcio_tag_status_read_immediate(spectx, mask, tag_status); 00329 default: 00330 errno = EINVAL; 00331 return -1; 00332 } 00333 }
int _base_spe_mssync_start | ( | spe_context_ptr_t | spectx | ) |
_base_spe_mssync_start starts Multisource Synchronisation
spectx | Specifies the SPE context |
Definition at line 335 of file dma.c.
References _base_spe_open_if_closed(), spe_context::base_private, FD_MSS, spe_context_base_priv::flags, spe_mssync_area::MFC_MSSync, spe_context_base_priv::mssync_mmap_base, and SPE_MAP_PS.
00336 { 00337 int ret, fd; 00338 unsigned int data = 1; /* Any value can be written here */ 00339 00340 volatile struct spe_mssync_area *mss_area = 00341 spectx->base_private->mssync_mmap_base; 00342 00343 if (spectx->base_private->flags & SPE_MAP_PS) { 00344 mss_area->MFC_MSSync = data; 00345 return 0; 00346 } else { 00347 fd = _base_spe_open_if_closed(spectx, FD_MSS, 0); 00348 if (fd != -1) { 00349 ret = write(fd, &data, sizeof (data)); 00350 if ((ret < 0) && (errno != EIO)) { 00351 perror("spe_mssync_start: internal error"); 00352 } 00353 return ret < 0 ? -1 : 0; 00354 } else 00355 return -1; 00356 } 00357 }
int _base_spe_mssync_status | ( | spe_context_ptr_t | spectx | ) |
_base_spe_mssync_status retrieves status of Multisource Synchronisation
spectx | Specifies the SPE context |
Definition at line 359 of file dma.c.
References _base_spe_open_if_closed(), spe_context::base_private, FD_MSS, spe_context_base_priv::flags, spe_mssync_area::MFC_MSSync, spe_context_base_priv::mssync_mmap_base, and SPE_MAP_PS.
00360 { 00361 int ret, fd; 00362 unsigned int data; 00363 00364 volatile struct spe_mssync_area *mss_area = 00365 spectx->base_private->mssync_mmap_base; 00366 00367 if (spectx->base_private->flags & SPE_MAP_PS) { 00368 return mss_area->MFC_MSSync; 00369 } else { 00370 fd = _base_spe_open_if_closed(spectx, FD_MSS, 0); 00371 if (fd != -1) { 00372 ret = read(fd, &data, sizeof (data)); 00373 if ((ret < 0) && (errno != EIO)) { 00374 perror("spe_mssync_start: internal error"); 00375 } 00376 return ret < 0 ? -1 : data; 00377 } else 00378 return -1; 00379 } 00380 }
int _base_spe_out_intr_mbox_read | ( | spe_context_ptr_t | spectx, | |
unsigned int | mbox_data[], | |||
int | count, | |||
int | behavior_flag | |||
) |
The _base_spe_out_intr_mbox_read function reads the contents of the SPE outbound interrupting mailbox for the SPE context.
Definition at line 255 of file mbox.c.
References _base_spe_open_if_closed(), FD_IBOX, FD_IBOX_NB, SPE_MBOX_ALL_BLOCKING, SPE_MBOX_ANY_BLOCKING, and SPE_MBOX_ANY_NONBLOCKING.
00259 { 00260 int rc; 00261 int total; 00262 00263 if (mbox_data == NULL || count < 1){ 00264 errno = EINVAL; 00265 return -1; 00266 } 00267 00268 switch (behavior_flag) { 00269 case SPE_MBOX_ALL_BLOCKING: // read all, even if blocking 00270 total = rc = 0; 00271 while (total < 4*count) { 00272 rc = read(_base_spe_open_if_closed(spectx,FD_IBOX, 0), 00273 (char *)mbox_data + total, 4*count - total); 00274 if (rc == -1) { 00275 break; 00276 } 00277 total += rc; 00278 } 00279 break; 00280 00281 case SPE_MBOX_ANY_BLOCKING: // read at least one, even if blocking 00282 total = rc = read(_base_spe_open_if_closed(spectx,FD_IBOX, 0), mbox_data, 4*count); 00283 break; 00284 00285 case SPE_MBOX_ANY_NONBLOCKING: // only reaad, if non blocking 00286 rc = read(_base_spe_open_if_closed(spectx,FD_IBOX_NB, 0), mbox_data, 4*count); 00287 if (rc == -1 && errno == EAGAIN) { 00288 rc = 0; 00289 errno = 0; 00290 } 00291 total = rc; 00292 break; 00293 00294 default: 00295 errno = EINVAL; 00296 return -1; 00297 } 00298 00299 if (rc == -1) { 00300 errno = EIO; 00301 return -1; 00302 } 00303 00304 return rc / 4; 00305 }
int _base_spe_out_intr_mbox_status | ( | spe_context_ptr_t | spectx | ) |
The _base_spe_out_intr_mbox_status function fetches the status of the SPU outbound interrupt mailbox for the SPE thread specified by the speid parameter. A 0 value is return if the mailbox is empty. A non-zero value specifies the number of 32-bit unread mailbox entries.
spectx | Specifies the SPE context whose mailbox status is to be read. |
Definition at line 238 of file mbox.c.
References _base_spe_open_if_closed(), spe_context::base_private, spe_context_base_priv::cntl_mmap_base, FD_IBOX_STAT, spe_context_base_priv::flags, SPE_MAP_PS, and spe_spu_control_area::SPU_Mbox_Stat.
00239 { 00240 int rc, ret; 00241 volatile struct spe_spu_control_area *cntl_area = 00242 spectx->base_private->cntl_mmap_base; 00243 00244 if (spectx->base_private->flags & SPE_MAP_PS) { 00245 ret = (cntl_area->SPU_Mbox_Stat >> 16) & 0xFF; 00246 } else { 00247 rc = read(_base_spe_open_if_closed(spectx,FD_IBOX_STAT, 0), &ret, 4); 00248 if (rc != 4) 00249 ret = -1; 00250 00251 } 00252 return ret; 00253 }
int _base_spe_out_mbox_read | ( | spe_context_ptr_t | spectx, | |
unsigned int | mbox_data[], | |||
int | count | |||
) |
The _base_spe_out_mbox_read function reads the contents of the SPE outbound interrupting mailbox for the SPE thread speid.
The call will not block until the read request is satisfied, but instead return up to count currently available mailbox entries.
spe_stat_out_intr_mbox can be called to ensure that data is available prior to reading the outbound interrupting mailbox.
spectx | Specifies the SPE thread whose outbound mailbox is to be read. | |
mbox_data | ||
count |
>0 | the number of 32-bit mailbox messages read | |
=0 | no data available | |
-1 | error condition and errno is set Possible values for errno: EINVAL speid is invalid Exxxx what else do we need here?? |
Definition at line 58 of file mbox.c.
References _base_spe_open_if_closed(), spe_context::base_private, DEBUG_PRINTF, FD_MBOX, spe_context_base_priv::flags, and SPE_MAP_PS.
00061 { 00062 int rc; 00063 00064 if (mbox_data == NULL || count < 1){ 00065 errno = EINVAL; 00066 return -1; 00067 } 00068 00069 if (spectx->base_private->flags & SPE_MAP_PS) { 00070 rc = _base_spe_out_mbox_read_ps(spectx, mbox_data, count); 00071 } else { 00072 rc = read(_base_spe_open_if_closed(spectx,FD_MBOX, 0), mbox_data, count*4); 00073 DEBUG_PRINTF("%s read rc: %d\n", __FUNCTION__, rc); 00074 if (rc != -1) { 00075 rc /= 4; 00076 } else { 00077 if (errno == EAGAIN ) { // no data ready to be read 00078 errno = 0; 00079 rc = 0; 00080 } 00081 } 00082 } 00083 return rc; 00084 }
int _base_spe_out_mbox_status | ( | spe_context_ptr_t | spectx | ) |
The _base_spe_out_mbox_status function fetches the status of the SPU outbound mailbox for the SPE thread specified by the speid parameter. A 0 value is return if the mailbox is empty. A non-zero value specifies the number of 32-bit unread mailbox entries.
spectx | Specifies the SPE context whose mailbox status is to be read. |
Definition at line 220 of file mbox.c.
References _base_spe_open_if_closed(), spe_context::base_private, spe_context_base_priv::cntl_mmap_base, FD_MBOX_STAT, spe_context_base_priv::flags, SPE_MAP_PS, and spe_spu_control_area::SPU_Mbox_Stat.
00221 { 00222 int rc, ret; 00223 volatile struct spe_spu_control_area *cntl_area = 00224 spectx->base_private->cntl_mmap_base; 00225 00226 if (spectx->base_private->flags & SPE_MAP_PS) { 00227 ret = cntl_area->SPU_Mbox_Stat & 0xFF; 00228 } else { 00229 rc = read(_base_spe_open_if_closed(spectx,FD_MBOX_STAT, 0), &ret, 4); 00230 if (rc != 4) 00231 ret = -1; 00232 } 00233 00234 return ret; 00235 00236 }
int _base_spe_program_load | ( | spe_context_ptr_t | spectx, | |
spe_program_handle_t * | program | |||
) |
_base_spe_program_load loads an ELF image into a context
spectx | Specifies the SPE context | |
program | handle to the ELF image |
Definition at line 203 of file load.c.
References _base_spe_load_spe_elf(), _base_spe_program_load_complete(), spe_context::base_private, DEBUG_PRINTF, spe_context_base_priv::emulated_entry, spe_ld_info::entry, spe_context_base_priv::entry, spe_context_base_priv::flags, spe_context_base_priv::loaded_program, spe_context_base_priv::mem_mmap_base, SPE_ISOLATE, and SPE_ISOLATE_EMULATE.
00204 { 00205 int rc = 0; 00206 struct spe_ld_info ld_info; 00207 00208 spe->base_private->loaded_program = program; 00209 00210 if (spe->base_private->flags & SPE_ISOLATE) { 00211 rc = spe_start_isolated_app(spe, program); 00212 00213 } else if (spe->base_private->flags & SPE_ISOLATE_EMULATE) { 00214 rc = spe_start_emulated_isolated_app(spe, program, &ld_info); 00215 00216 } else { 00217 rc = _base_spe_load_spe_elf(program, 00218 spe->base_private->mem_mmap_base, &ld_info); 00219 if (!rc) 00220 _base_spe_program_load_complete(spe); 00221 } 00222 00223 if (rc != 0) { 00224 DEBUG_PRINTF ("Load SPE ELF failed..\n"); 00225 return -1; 00226 } 00227 00228 spe->base_private->entry = ld_info.entry; 00229 spe->base_private->emulated_entry = ld_info.entry; 00230 00231 return 0; 00232 }
void _base_spe_program_load_complete | ( | spe_context_ptr_t | spectx | ) |
Signal that the program load has completed. For normal apps, this is called directly in the load path. For (emulated) isolated apps, the load is asynchronous, so this needs to be called when we know that the load has completed
spectx | The spe context that has been loaded. |
Register the SPE program's start address with the oprofile and gdb, by writing to the object-id file.
Definition at line 38 of file load.c.
References __spe_context_update_event(), spe_context::base_private, DEBUG_PRINTF, spe_program_handle::elf_image, spe_context_base_priv::fd_spe_dir, and spe_context_base_priv::loaded_program.
Referenced by _base_spe_context_run(), and _base_spe_program_load().
00039 { 00040 int objfd, len; 00041 char buf[20]; 00042 spe_program_handle_t *program; 00043 00044 program = spectx->base_private->loaded_program; 00045 00046 if (!program || !program->elf_image) { 00047 DEBUG_PRINTF("%s called, but no program loaded\n", __func__); 00048 return; 00049 } 00050 00051 objfd = openat(spectx->base_private->fd_spe_dir, "object-id", O_RDWR); 00052 if (objfd < 0) 00053 return; 00054 00055 len = sprintf(buf, "%p", program->elf_image); 00056 write(objfd, buf, len + 1); 00057 close(objfd); 00058 00059 __spe_context_update_event(); 00060 }
void* _base_spe_ps_area_get | ( | struct spe_context * | spectx, | |
enum ps_area | area | |||
) |
_base_spe_ps_area_get returns a pointer to the start of memory mapped problem state area
spectx | Specifies the SPE context | |
area | specifes the area to map |
int _base_spe_signal_write | ( | spe_context_ptr_t | spectx, | |
unsigned int | signal_reg, | |||
unsigned int | data | |||
) |
The _base_spe_signal_write function writes data to the signal notification register specified by signal_reg for the SPE thread specified by the speid parameter.
spectx | Specifies the SPE context whose signal register is to be written to. | |
signal_reg | Specified the signal notification register to be written. Valid signal notification registers are: SPE_SIG_NOTIFY_REG_1 SPE signal notification register 1 SPE_SIG_NOTIFY_REG_2 SPE signal notification register 2 | |
data | The 32-bit data to be written to the specified signal notification register. |
Definition at line 307 of file mbox.c.
References _base_spe_close_if_open(), _base_spe_open_if_closed(), spe_context::base_private, FD_SIG1, FD_SIG2, spe_context_base_priv::flags, spe_context_base_priv::signal1_mmap_base, spe_context_base_priv::signal2_mmap_base, SPE_MAP_PS, SPE_SIG_NOTIFY_REG_1, SPE_SIG_NOTIFY_REG_2, spe_sig_notify_1_area::SPU_Sig_Notify_1, and spe_sig_notify_2_area::SPU_Sig_Notify_2.
00310 { 00311 int rc; 00312 00313 if (spectx->base_private->flags & SPE_MAP_PS) { 00314 if (signal_reg == SPE_SIG_NOTIFY_REG_1) { 00315 spe_sig_notify_1_area_t *sig = spectx->base_private->signal1_mmap_base; 00316 00317 sig->SPU_Sig_Notify_1 = data; 00318 } else if (signal_reg == SPE_SIG_NOTIFY_REG_2) { 00319 spe_sig_notify_2_area_t *sig = spectx->base_private->signal2_mmap_base; 00320 00321 sig->SPU_Sig_Notify_2 = data; 00322 } else { 00323 errno = EINVAL; 00324 return -1; 00325 } 00326 rc = 0; 00327 } else { 00328 if (signal_reg == SPE_SIG_NOTIFY_REG_1) 00329 rc = write(_base_spe_open_if_closed(spectx,FD_SIG1, 0), &data, 4); 00330 else if (signal_reg == SPE_SIG_NOTIFY_REG_2) 00331 rc = write(_base_spe_open_if_closed(spectx,FD_SIG2, 0), &data, 4); 00332 else { 00333 errno = EINVAL; 00334 return -1; 00335 } 00336 00337 if (rc == 4) 00338 rc = 0; 00339 00340 if (signal_reg == SPE_SIG_NOTIFY_REG_1) 00341 _base_spe_close_if_open(spectx,FD_SIG1); 00342 else if (signal_reg == SPE_SIG_NOTIFY_REG_2) 00343 _base_spe_close_if_open(spectx,FD_SIG2); 00344 } 00345 00346 return rc; 00347 }
int _base_spe_stop_reason_get | ( | spe_context_ptr_t | spectx | ) |
_base_spe_stop_reason_get
spectx | one thread for which to check why it was stopped |
0 | success - eventid and eventdata set appropriately | |
1 | spe has not stopped after checking last, so no data was written to event | |
-1 | an error has happened, event was not touched, errno gets set Possible vales for errno: EINVAL speid is invalid Exxxx what else do we need here?? |
int _base_spe_stop_status_get | ( | spe_context_ptr_t | spectx | ) |
_base_spe_stop_status_get
spectx | Specifies the SPE context |