Commit | Line | Data |
---|---|---|
920dae64 AT |
1 | /* |
2 | * ========== Copyright Header Begin ========================================== | |
3 | * | |
4 | * OpenSPARC T2 Processor File: magictraps.c | |
5 | * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. | |
6 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES. | |
7 | * | |
8 | * The above named program is free software; you can redistribute it and/or | |
9 | * modify it under the terms of the GNU General Public | |
10 | * License version 2 as published by the Free Software Foundation. | |
11 | * | |
12 | * The above named program is distributed in the hope that it will be | |
13 | * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
15 | * General Public License for more details. | |
16 | * | |
17 | * You should have received a copy of the GNU General Public | |
18 | * License along with this work; if not, write to the Free Software | |
19 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. | |
20 | * | |
21 | * ========== Copyright Header End ============================================ | |
22 | */ | |
23 | /* | |
24 | * Copyright 2006 Sun Microsystems, Inc. All rights reserved. | |
25 | * Use is subject to license terms. | |
26 | */ | |
27 | ||
28 | #pragma ident "@(#)magictraps.c 1.5 06/10/27 SMI" | |
29 | ||
30 | #include <stdio.h> | |
31 | #include <stdlib.h> | |
32 | #include <strings.h> | |
33 | ||
34 | #include "basics.h" | |
35 | #include "fatal.h" | |
36 | #include "simcore.h" | |
37 | #include "config.h" | |
38 | #include "tsparcv9.h" | |
39 | #include "tsparcv9internal.h" | |
40 | #include "sparcv9regs.h" | |
41 | #include "magictraps.h" | |
42 | #include "options.h" | |
43 | ||
44 | #if ENABLE_MAGIC_TRAPS /* { */ | |
45 | ||
46 | static uint64_t | |
47 | pabcopy(simcpu_t *sp, uint64_t pasrc, uint64_t padst, uint64_t size) | |
48 | { | |
49 | domain_t *domainp; | |
50 | config_proc_t *config_procp; | |
51 | config_addr_t *capsrc, *capdst; | |
52 | uint8_t *srcbufp, *dstbufp; | |
53 | tpaddr_t extent; | |
54 | ||
55 | DBG( lprintf(sp->gid, "pabcopy(0x%llx, 0x%llx, 0x%llx)\n", | |
56 | pasrc, padst, size); ); | |
57 | ||
58 | config_procp = sp->config_procp; | |
59 | domainp = config_procp->domainp; | |
60 | ||
61 | capsrc = find_domain_address(domainp, pasrc); | |
62 | if (capsrc == NULL) { | |
63 | EXEC_WARNING(("@ pc=0x%llx : simbcopy: src address not valid", | |
64 | sp->pc)); | |
65 | return (-1); | |
66 | } | |
67 | /* try and get the buffer pointer */ | |
68 | extent = capsrc->config_devp->dev_typep->dev_cacheable(capsrc, DA_Load, | |
69 | pasrc-capsrc->baseaddr, &srcbufp); | |
70 | if (extent < size) { | |
71 | EXEC_WARNING(("@ pc=0x%llx : pabcopy: src not large enough", | |
72 | sp->pc)); | |
73 | return (-1); | |
74 | } | |
75 | ||
76 | capdst = find_domain_address(domainp, padst); | |
77 | if (capdst == NULL) { | |
78 | EXEC_WARNING(("@ pc=0x%llx : pabcopy: dest address not valid", | |
79 | sp->pc)); | |
80 | return (-1); | |
81 | } | |
82 | /* try and get the buffer pointer */ | |
83 | extent = capdst->config_devp->dev_typep->dev_cacheable(capdst, DA_Store, | |
84 | padst-capdst->baseaddr, &dstbufp); | |
85 | if (extent < size) { | |
86 | EXEC_WARNING(("@ pc=0x%llx : pabcopy: dest not large enough", | |
87 | sp->pc)); | |
88 | return (-1); | |
89 | } | |
90 | ||
91 | bcopy(srcbufp, dstbufp, size); | |
92 | return (0); | |
93 | } | |
94 | ||
95 | /* | |
96 | * Called from a trap instruction implementation if a trap falls | |
97 | * into the magic trap number range - see the macro SS_MAGIC_TRAP(). | |
98 | * | |
99 | * Returns true to indicate the magic trap was actioned, false | |
100 | * otherwise. Typically, the call sequence is: | |
101 | * | |
102 | * if (SS_MAGIC_TRAP(sp, tt)) { | |
103 | * NEXT_INSTN(sp); | |
104 | * return; | |
105 | * } | |
106 | */ | |
107 | ||
108 | bool_t ss_magic_trap(simcpu_t * sp, uint32_t tt) | |
109 | { | |
110 | sparcv9_cpu_t * v9p; | |
111 | ||
112 | if (!options.magic_traps) | |
113 | return false; | |
114 | ||
115 | v9p = (sparcv9_cpu_t *)(sp->specificp); | |
116 | ||
117 | switch (tt) { | |
118 | ||
119 | case MAGIC_TRAP_SETDBG: | |
120 | if (v9p->state == V9_User) | |
121 | return false; | |
122 | { | |
123 | uint64_t val; | |
124 | int i; | |
125 | #if NDEBUG /* { */ | |
126 | EXEC_WARNING(("Magic trap 0x%x: compiled with NDEBUG," | |
127 | "so no simulator debug output", tt)); | |
128 | val = 0; | |
129 | #else /* } { */ | |
130 | ||
131 | val = debug_bits; | |
132 | simcore_update_debug_bits( sp->intreg[Reg_sparcv9_o0] ); | |
133 | #endif /* } */ | |
134 | sp->intreg[Reg_sparcv9_o0] = val; | |
135 | } | |
136 | return true; | |
137 | ||
138 | case MAGIC_TRAP_SIMEXIT: | |
139 | if (v9p->state == V9_User) | |
140 | break; | |
141 | /* Use for dramatic exit */ | |
142 | log_flush(); | |
143 | warning("magic trap 0x%x requested exit(0x%llx)\n", tt, | |
144 | sp->intreg[Reg_sparcv9_o0]); | |
145 | exit(sp->intreg[Reg_sparcv9_o0]); | |
146 | ||
147 | case MAGIC_TRAP_GOT_HERE: { | |
148 | if (v9p->state == V9_User) | |
149 | return false; | |
150 | log_lock(); | |
151 | log_printf(sp->gid, "Got here: 0x%llx\n", sp->pc); | |
152 | #if !defined(NDEBUG) /* { */ | |
153 | sparcv9_dump_state(sp); | |
154 | #endif /* } */ | |
155 | log_flush_unlock(); | |
156 | ||
157 | return true; | |
158 | } | |
159 | ||
160 | case MAGIC_TRAP_LOG_DUMP: /* rot log dump */ | |
161 | if (v9p->state == V9_User) | |
162 | return false; | |
163 | #if !defined(NDEBUG) /* { */ | |
164 | log_dump(); | |
165 | #endif /* } */ | |
166 | return true; | |
167 | ||
168 | case MAGIC_TRAP_PABCOPY: { /* pa bcopy */ | |
169 | if (v9p->state != V9_RED && v9p->state != V9_HyperPriv) | |
170 | return false; | |
171 | sp->intreg[Reg_sparcv9_g4] = | |
172 | pabcopy(sp, sp->intreg[Reg_sparcv9_g1], | |
173 | sp->intreg[Reg_sparcv9_g2], | |
174 | sp->intreg[Reg_sparcv9_g3]); | |
175 | return true; | |
176 | } | |
177 | ||
178 | case MAGIC_TRAP_INST_CNT: { /* instruction count */ | |
179 | uint64_t temp_flags; | |
180 | simcycle_t count; | |
181 | ||
182 | if (v9p->state == V9_User) | |
183 | return false; | |
184 | count = ICOUNT(sp); | |
185 | temp_flags = sp->intreg[Reg_sparcv9_o0]; | |
186 | ||
187 | if (temp_flags & MT_INST_CNT_PRINT) { | |
188 | lprintf(sp->gid, "At: %llu : " | |
189 | "Instruction count = %llu\n", (uint64_t)count, | |
190 | (uint64_t)(count - sp->magic_count)); | |
191 | } | |
192 | if (temp_flags & MT_INST_CNT_SET_PREV) { | |
193 | sp->magic_count = count; | |
194 | } | |
195 | return true; | |
196 | } | |
197 | ||
198 | case MAGIC_TRAP_ALLDBG: { | |
199 | if (v9p->state == V9_User) | |
200 | return false; | |
201 | #if NDEBUG /* { */ | |
202 | EXEC_WARNING(("Magic trap 0x%x: compiled with NDEBUG," | |
203 | "so no simulator debug output", tt)); | |
204 | #else /* } { */ | |
205 | simcore_update_debug_bits(-1); | |
206 | #endif /* } */ | |
207 | return true; | |
208 | } | |
209 | case MAGIC_TRAP_NO_DBG: { | |
210 | if (v9p->state == V9_User) | |
211 | return false; | |
212 | #if NDEBUG /* { */ | |
213 | EXEC_WARNING(("Magic trap 0x%x: compiled with NDEBUG," | |
214 | "so no simulator debug output", tt)); | |
215 | #else /* } { */ | |
216 | simcore_update_debug_bits(0); | |
217 | #endif /* } */ | |
218 | return true; | |
219 | } | |
220 | case MAGIC_TRAP_SAVE_STATE: { | |
221 | ||
222 | flockfile(stdout); | |
223 | ||
224 | lprintf(sp->gid, "MAGIC_TRAP_SAVE_STATE: Got here: 0x%llx (instn_cnt=%lld)\n", | |
225 | sp->pc, ICOUNT(sp)); | |
226 | ||
227 | if (sp->config_procp->proc_typep->save_state(sp) == false) { | |
228 | funlockfile(stdout); | |
229 | fatal("Legion Save State Failed. Exiting!\n"); | |
230 | } | |
231 | ||
232 | /* We are done, so terminate legion with a Message */ | |
233 | funlockfile(stdout); | |
234 | lprintf(sp->gid, "Legion Save State Completed. Exiting\n"); | |
235 | exit(0); | |
236 | } | |
237 | default: | |
238 | return false; | |
239 | } | |
240 | /* no return here - compiler will catch errors in the switch */ | |
241 | } | |
242 | ||
243 | #endif /* } */ |