PS2SDK
PS2 Homebrew Libraries
Loading...
Searching...
No Matches
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"
29IRX_ID(MODNAME, 1, 1);
30
31extern struct irx_export_table _exp_ioptrap;
32
33
34static 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
52const char *get_exception_name(exception_type_t type)
53{
54 return exception_type_name[type];
55}
56
57exception_frame_t __trap_frame;
58extern void def_exc_handler();
59extern void bp_exc_handler();
60
61int dbg_jmp_buf_setup = 0;
62jmp_buf dbg_jmp_buf;
63
64exception_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. */
79typedef 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
112char *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
145static trap_exception_handler_t handlers[16];
146
147trap_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
154trap_exception_handler_t get_exception_handler(exception_type_t type)
155{
156 return handlers[type];
157}
158
159void 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
213static 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
228void 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
246int 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
258void 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
268int _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
293int shutdown()
294{
295 return 0;
296}
#define IOP_EXCEPTION_HDB
Definition excepman.h:58
unsigned int version
Definition fileXio.h:3
struct _smod_mod_info smod_mod_info_t
u16 newflags
Definition smod.h:30
char * name
Definition smod.h:27
u32 entry
Definition smod.h:34
int smod_get_next_mod(smod_mod_info_t *cur_mod, smod_mod_info_t *next_mod)
Definition smod.c:30