00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00035 #ifndef CTRUMP_LIBSPE2_SPE_H
00036 #define CTRUMP_LIBSPE2_SPE_H
00037
00038 #include <stdint.h>
00039 #include <string.h>
00040 #include <spu_mfcio.h>
00041
00042 #ifdef __cplusplus
00043 extern "C" {
00044 #endif
00045
00046 #ifndef _ELF_H
00047 typedef uint32_t Elf32_Word;
00048 typedef uint16_t Elf32_Half;
00049 typedef uint32_t Elf32_Off;
00050 typedef uint32_t Elf32_Addr;
00051 #define PT_LOAD 1
00052 #endif
00053
00054 #ifdef ADDR64
00055 typedef uint64_t ctrump_ea_t;
00056 #else
00057 typedef uint32_t ctrump_ea_t;
00058 #endif
00059
00063 struct ctrump_ehdr{
00064 unsigned char e_ident[16];
00065 Elf32_Half e_type;
00066 Elf32_Half e_machine;
00067 Elf32_Word e_version;
00068 Elf32_Addr e_entry;
00069 Elf32_Off e_phoff;
00070 Elf32_Off e_shoff;
00071 Elf32_Word e_flags;
00072 Elf32_Half e_ehsize;
00073 Elf32_Half e_phentsize;
00074 Elf32_Half e_phnum;
00075 };
00076
00080 struct ctrump_phdr {
00081 Elf32_Word p_type;
00082 Elf32_Off p_offset;
00083 Elf32_Addr p_vaddr;
00084 Elf32_Addr p_paddr;
00085 Elf32_Word p_filesz;
00086 Elf32_Word p_memsz;
00087 Elf32_Word p_flags;
00088 Elf32_Word p_align;
00089 };
00090
00091 typedef struct ctrump_ehdr ehdr;
00092
00093 extern char ctrump_begin;
00094 extern char ctrump_end;
00095
00103 static void
00104 ctrump_libspe2_program_boot(ctrump_ea_t prog_handle,
00105 unsigned long long argp, unsigned long long envp) __attribute__((noinline,noreturn));
00106
00107 static void
00108 ctrump_libspe2_program_boot(ctrump_ea_t prog_handle,
00109 register unsigned long long argp,
00110 register unsigned long long envp)
00111 {
00112 struct ctrump_ehdr *ehdr;
00113 unsigned int mod128 = ((int)prog_handle)&127;
00114 ctrump_ea_t addr;
00115 ctrump_ea_t ph_ea;
00116 int phnum, phentsize, i;
00117 unsigned char *phdr_ls;
00118 unsigned char *prog_buf;
00119 void (*entry)(void);
00120
00121 unsigned char tmp_buf_una[1024+128];
00122 unsigned int this_size = &ctrump_end - &ctrump_begin;
00123
00124 unsigned char *tmp_buf = (unsigned char*)(((int)(tmp_buf_una + 127))&~127);
00125
00126 prog_buf = tmp_buf + 256;
00127
00128 mfc_get(tmp_buf, prog_handle-mod128, 256, 0, 0, 0);
00129 mfc_write_tag_mask(1);
00130 mfc_read_tag_status_all();
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143 addr = *(ctrump_ea_t*)(tmp_buf + mod128 + sizeof(ctrump_ea_t));
00144
00145 mod128 = ((int)addr) & 127;
00146
00147 mfc_get(tmp_buf, addr-mod128, 256, 0, 0, 0);
00148 mfc_write_tag_mask(1);
00149 mfc_read_tag_status_all();
00150
00151 ehdr = (struct ctrump_ehdr*)(tmp_buf + mod128);
00152
00153 ph_ea = addr + ehdr->e_phoff;
00154 mod128 = ((int)ph_ea) & 127;
00155
00156 phnum = ehdr->e_phnum;
00157 phentsize = ehdr->e_phentsize;
00158 entry = (void (*)())ehdr->e_entry;
00159
00160 mfc_get(tmp_buf, ph_ea-mod128, 256, 0, 0, 0);
00161 mfc_write_tag_mask(1);
00162 mfc_read_tag_status_all();
00163
00164 phdr_ls = tmp_buf + mod128;
00165
00166 memcpy(prog_buf, &ctrump_begin, this_size);
00167
00168 spu_sync();
00169
00170 __asm__ volatile ("bi %0\n\t.align 4\n\tctrump_begin:"::"r"(prog_buf));
00171
00172 for (i=0; i<phnum; i++) {
00173 register struct ctrump_phdr *ph = (struct ctrump_phdr*)phdr_ls;
00174 if (ph->p_type == PT_LOAD) {
00175 register unsigned int paddr = ph->p_paddr;
00176 register unsigned int off = ph->p_offset;
00177 register unsigned int memsz = ph->p_memsz;
00178 register unsigned int fsz = ph->p_filesz;
00179 register int clear_size = memsz - fsz;
00180 register vector unsigned char *bss = (vector unsigned char*)(paddr + fsz);
00181 register unsigned int paddr_off = 0;
00182 phdr_ls += phentsize;
00183
00184 while (fsz > 0) {
00185 register int get_size = fsz>16384?16384:fsz;
00186 mfc_get((unsigned char*)paddr + paddr_off, addr+off, get_size, 0, 0, 0);
00187 paddr_off += get_size;
00188 off += get_size;
00189 fsz -= get_size;
00190 }
00191
00192
00193 while (clear_size > 0) {
00194 *bss = spu_splats((unsigned char)0);
00195 bss++;
00196 clear_size -= 16;
00197 }
00198 }
00199 }
00200
00201 mfc_write_tag_mask(~0);
00202 mfc_read_tag_status_all();
00203
00204 spu_sync();
00205
00206 __asm__ volatile ("ori $4, %0, 0\n\t"::"r"(argp):"4");
00207 __asm__ volatile ("ori $5, %0, 0\n\t"::"r"(envp):"5");
00208 __asm__ volatile ("bi %0\n\t"
00209 "ctrump_end:":: "r"(entry));
00210 while(1);
00211 }
00212
00213
00221 static inline int
00222 ctrump_spe_fini(int spe_id, int is_last_spe, unsigned long long sync_ea)
00223 {
00224 static unsigned int sync_buffer[32] __attribute__((aligned(128)));
00225 unsigned int prog_lo, prog_hi;
00226 unsigned int param_lo, param_hi;
00227 unsigned long long prog_ea;
00228 unsigned long long param;
00229 int r, ev;
00230
00231 if (is_last_spe) {
00232
00233 spu_write_event_mask(MFC_LLR_LOST_EVENT);
00234
00235 while (1) {
00236 mfc_getllar(sync_buffer, sync_ea, 0, 0);
00237 mfc_read_atomic_status();
00238
00239 if (sync_buffer[0] == spe_id)
00240 break;
00241
00242 ev = spu_readch(SPU_RdEventStat);
00243 spu_write_event_ack(ev & MFC_LLR_LOST_EVENT);
00244 }
00245
00246 spu_write_out_intr_mbox(0);
00247 } else {
00248
00249 while (1) {
00250 mfc_getllar(sync_buffer, sync_ea, 0, 0);
00251 mfc_read_atomic_status();
00252
00253 sync_buffer[0]++;
00254
00255 mfc_putllc(sync_buffer, sync_ea, 0, 0);
00256 r = mfc_read_atomic_status();
00257
00258 if (__builtin_expect((r & MFC_PUTLLC_STATUS) == 0, 1) ) {
00259 break;
00260 }
00261 }
00262 }
00263
00264 prog_lo = spu_read_in_mbox();
00265 if (prog_lo == 0xffffffff)
00266 return -1;
00267
00268 prog_hi = spu_read_in_mbox();
00269
00270 param_lo = spu_read_in_mbox();
00271 param_hi = spu_read_in_mbox();
00272
00273 prog_ea = (((unsigned long long)prog_hi)<<32) | prog_lo;
00274 param = (((unsigned long long)param_hi)<<32) | param_lo;
00275
00276 ctrump_libspe2_program_boot(prog_ea, param, 0);
00277 return 0;
00278 }
00279
00283 static inline void
00284 ctrump_spe_wait_ppe(void)
00285 {
00286 unsigned int prog_lo, prog_hi;
00287 unsigned int param_lo, param_hi;
00288 unsigned long long prog_ea;
00289 unsigned long long param;
00290 spu_write_out_intr_mbox(0);
00291 prog_lo = spu_read_in_mbox();
00292 if (prog_lo == 0xffffffff)
00293 return;
00294
00295 prog_hi = spu_read_in_mbox();
00296
00297 param_lo = spu_read_in_mbox();
00298 param_hi = spu_read_in_mbox();
00299
00300 prog_ea = (((unsigned long long)prog_hi)<<32) | prog_lo;
00301 param = (((unsigned long long)param_hi)<<32) | param_lo;
00302
00303 ctrump_libspe2_program_boot(prog_ea, param, 0);
00304 }
00305
00306
00307 #ifdef __cplusplus
00308 }
00309 #endif
00310 #endif