Initial commit of OpenSPARC T2 architecture model.
[OpenSPARC-T2-SAM] / legion / src / procs / sparcv9 / magictraps.c
CommitLineData
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
46static uint64_t
47pabcopy(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
108bool_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 /* } */