PS2SDK
PS2 Homebrew Libraries
ioptrap.c
Go to the documentation of this file.
1 /*
2 # _____ ___ ____ ___ ____
3 # ____| | ____| | | |____|
4 # | ___| |____ ___| ____| | \ PS2DEV Open Source Project.
5 #-----------------------------------------------------------------------
6 # Copyright 2001-2004, ps2dev - http://www.ps2dev.org
7 # Licenced under Academic Free License version 2.0
8 # Review ps2sdk README & LICENSE files for further details.
9 */
10 
16 #include "types.h"
17 #include "defs.h"
18 #include "irx.h"
19 
20 #include "ioptrap.h"
21 
22 #include "excepman.h"
23 #include "loadcore.h"
24 #include "sifman.h"
25 #include "stdio.h"
26 #include "sysclib.h"
27 #include "thbase.h"
28 #define MODNAME "ioptrap_driver"
29 IRX_ID(MODNAME, 1, 1);
30 
31 extern struct irx_export_table _exp_ioptrap;
32 
33 
34 static const char *exception_type_name[] = {
35  "Interrupt",
36  "TLB Modification",
37  "TLB Miss Load",
38  "TLB Miss Store",
39  "Address Error Load",
40  "Address Error Store",
41  "Instruction Bus Error",
42  "Data Bus Error",
43  "Syscall",
44  "Breakpoint",
45  "Reserved Instruction",
46  "Coprocessor Unusable",
47  "Overflow",
48  "Reserved 13",
49  "Reserved 14" /* "Floating point exception" */
50 };
51 
52 const char *get_exception_name(exception_type_t type)
53 {
54  return exception_type_name[type];
55 }
56 
57 exception_frame_t __trap_frame;
58 extern void def_exc_handler();
59 extern void bp_exc_handler();
60 
61 int dbg_jmp_buf_setup = 0;
62 jmp_buf dbg_jmp_buf;
63 
64 exception_type_t dbg_setjmp()
65 {
66  int v;
67  if (0 == (v = setjmp(dbg_jmp_buf))) {
68  dbg_jmp_buf_setup = 1;
69  } else {
70  dbg_jmp_buf_setup = 0;
71  }
72  return v;
73 }
74 
75 #ifdef IOPTRAP_PRINT_MODULE_NAME
76 // from ps2link
77 
78 /* Module info entry. */
79 typedef struct _smod_mod_info
80 {
81  struct _smod_mod_info *next;
82  char *name;
83  u16 version;
84  u16 newflags; /* For modload shipped with games. */
85  u16 id;
86  u16 flags; /* I believe this is where flags are kept for BIOS versions. */
87  u32 entry; /* _start */
88  u32 gp;
89  u32 text_start;
90  u32 text_size;
91  u32 data_size;
92  u32 bss_size;
93  u32 unused1;
94  u32 unused2;
96 
97 
99 {
100  /* If cur_mod is 0, return the head of the list (IOP address 0x800). */
101  if (!cur_mod) {
102  return (smod_mod_info_t *)0x800;
103  } else {
104  if (!cur_mod->next)
105  return 0;
106  else
107  return cur_mod->next;
108  }
109  return 0;
110 }
111 
112 char *ExceptionGetModuleName(u32 epc, u32 *r_epc)
113 {
114  smod_mod_info_t *mod_info = 0;
115 
116  while ((mod_info = smod_get_next_mod(mod_info)) != 0) {
117  if ((epc >= mod_info->text_start) && (epc <= (mod_info->text_start + mod_info->text_size))) {
118  if (r_epc)
119  *r_epc = epc - mod_info->text_start;
120 
121  return mod_info->name;
122  }
123  }
124 
125  return 0;
126 }
127 #endif
128 
129 #define JUMP_BUF_PC 0
130 #define JUMP_BUF_SP 1
131 #define JUMP_BUF_FP 2
132 #define JUMP_BUF_S0 3
133 #define JUMP_BUF_S1 4
134 #define JUMP_BUF_S2 5
135 #define JUMP_BUF_S3 6
136 #define JUMP_BUF_S4 7
137 #define JUMP_BUF_S5 8
138 #define JUMP_BUF_S6 9
139 #define JUMP_BUF_S7 10
140 #define JUMP_BUF_GP 11
141 
142 // Define this to something else if you want... maybe some ee_sio stuff :P
143 #define TRAP_PRINTF(args...) printf(MODNAME ": " args)
144 
145 static trap_exception_handler_t handlers[16];
146 
147 trap_exception_handler_t set_exception_handler(exception_type_t type, trap_exception_handler_t handler)
148 {
149  trap_exception_handler_t old_handler = handlers[type];
150  handlers[type] = handler;
151  return old_handler;
152 }
153 
154 trap_exception_handler_t get_exception_handler(exception_type_t type)
155 {
156  return handlers[type];
157 }
158 
159 void trap(exception_type_t type, struct exception_frame *ex)
160 {
161  u32 i;
162 #ifdef IOPTRAP_PRINT_MODULE_NAME
163  u32 r_addr;
164  char *module;
165 #endif
166  if (dbg_jmp_buf_setup) {
167  u32 *p = (u32 *)dbg_jmp_buf;
168  /* simulate longjmp */
169  ex->epc = p[JUMP_BUF_PC];
170  ex->regs[29] = p[JUMP_BUF_SP];
171  ex->regs[30] = p[JUMP_BUF_FP];
172  ex->regs[16] = p[JUMP_BUF_S0];
173  ex->regs[17] = p[JUMP_BUF_S1];
174  ex->regs[18] = p[JUMP_BUF_S2];
175  ex->regs[19] = p[JUMP_BUF_S3];
176  ex->regs[20] = p[JUMP_BUF_S4];
177  ex->regs[21] = p[JUMP_BUF_S5];
178  ex->regs[22] = p[JUMP_BUF_S6];
179  ex->regs[23] = p[JUMP_BUF_S7];
180  ex->regs[28] = p[JUMP_BUF_GP];
181  ex->regs[2] = type; /* return value from setjmp */
182  return;
183  }
184  TRAP_PRINTF("IOP Exception : %s\n", exception_type_name[type]);
185  TRAP_PRINTF("EPC=%08x CAUSE=%08x SR=%08x BADVADDR=%08x DCIC=%08x\n", ex->epc, ex->cause, ex->sr, ex->badvaddr, ex->dcic);
186 #ifdef IOPTRAP_PRINT_MODULE_NAME
187  if ((module = ExceptionGetModuleName(ex->epc, &r_addr)))
188  TRAP_PRINTF("module %s at unreloc offset %08lX\n", module, r_addr);
189  if ((module = ExceptionGetModuleName(ex->regs[31], &r_addr)))
190  TRAP_PRINTF("ra module %s at unreloc offset %08lX\n", module, r_addr);
191 #endif
192  for (i = 0; i != 32; i += 4) {
193  TRAP_PRINTF("r[%02d]=%08x r[%02d]=%08x r[%02d]=%08x r[%02d]=%08x",
194  i, ex->regs[i], i + 1, ex->regs[i + 1], i + 2, ex->regs[i + 2], i + 3, ex->regs[i + 3]);
195  }
196 
197  if (handlers[type]) {
198  handlers[type](type, ex);
199  }
200 
201  if (type == EXCEPTION_Bp) {
202  ex->dcic = 0;
203  } else {
204  if (ex->cause & (((u32)1) << 31)) {
205  ex->cause &= ~(((u32)1) << 31); /* clear BD */
206  } else {
207  ex->epc += 4;
208  }
209  }
210 }
211 
212 #ifdef TEST_TRAP
213 static void trigger()
214 {
215  u32 v;
216  printf("trigger=%p\n", trigger);
217  printf("badaddr\n");
218  if (0 == (v = setjmp(dbg_jmp_buf))) {
219  dbg_jmp_buf_setup = 1;
220  *(u32 *)0xdeadbeef = 0xfeedface;
221  } else {
222  printf("exception occurred in command, v=%08x\n", v);
223  }
224  dbg_jmp_buf_setup = 0;
225  printf("done.\n");
226 }
227 
228 void main_thread(void *unused)
229 {
230  int i = 0;
231 
232  DelayThread(1000 * 1000);
233 
234  printf("IOP: about to trap!\n");
235  trigger();
236  printf("IOP: back from trap!\n");
237  while (1) {
238  printf("IOP: still running %d\n", i++);
239  DelayThread(2000 * 1000);
240  if (i == 10)
241  break;
242  }
243  ExitDeleteThread();
244 }
245 
246 int create_main_thread(void)
247 {
249 
250  thread.attr = 0x2000000;
251  thread.option = 0;
252  thread.thread = main_thread;
253  thread.stacksize = 0x8000;
254  thread.priority = 0x18;
255  return CreateThread(&thread);
256 }
257 
258 void do_tests()
259 {
260  int thid;
261  thid = create_main_thread();
262  StartThread(thid, NULL);
263 }
264 #else
265 #define do_tests()
266 #endif
267 
268 int _start(int argc, char *argv[])
269 {
270  int rv;
271 
272  (void)argc;
273  (void)argv;
274 
275  if (RegisterLibraryEntries(&_exp_ioptrap) != 0)
276  return MODULE_NO_RESIDENT_END;
277 
278  memset(handlers, 0, sizeof(trap_exception_handler_t) * 16);
279  printf("ioptrap starts.\n");
280  if ((rv = RegisterDefaultExceptionHandler((exception_handler_t)def_exc_handler)) < 0) {
281  printf("RegisterDefaultExceptionHandler failed, rv=%d\n", rv);
282  return MODULE_NO_RESIDENT_END;
283  }
284  if ((rv = RegisterPriorityExceptionHandler(IOP_EXCEPTION_HDB, 0, (exception_handler_t)bp_exc_handler)) < 0) {
285  // shouldn't we release the default exception handler here... ?
286  printf("RegisterDefaultExceptionHandler failed, rv=%d\n", rv);
287  return MODULE_NO_RESIDENT_END;
288  }
289  do_tests();
290  return MODULE_RESIDENT_END;
291 }
292 
293 int shutdown()
294 {
295  return 0;
296 }
exception_frame
Definition: ioptrap.h:41
thbase.h
sifman.h
sysclib.h
excepman.h
thread
Definition: thcommon.h:143
loadcore.h
_smod_mod_info::name
char * name
Definition: smod.h:27
_smod_mod_info
Definition: smod.h:24
irx.h
irx_export_table
Definition: irx.h:90
_exception_handler_struct_t
Definition: excepman.h:60
stdio.h
_iop_thread
Definition: thbase.h:39
_smod_mod_info::entry
u32 entry
Definition: smod.h:34
smod_mod_info_t
struct _smod_mod_info smod_mod_info_t
defs.h
IOP_EXCEPTION_HDB
#define IOP_EXCEPTION_HDB
Definition: excepman.h:58
_smod_mod_info::newflags
u16 newflags
Definition: smod.h:30
ioptrap.h
smod_get_next_mod
int smod_get_next_mod(smod_mod_info_t *cur_mod, smod_mod_info_t *next_mod)
Definition: smod.c:30