Initial commit of OpenSPARC T2 architecture model.
[OpenSPARC-T2-SAM] / sam-t2 / sam / system / blaze / dr.cc
CommitLineData
920dae64
AT
1// ========== Copyright Header Begin ==========================================
2//
3// OpenSPARC T2 Processor File: dr.cc
4// Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved.
5// DO NOT ALTER OR REMOVE COPYRIGHT NOTICES.
6//
7// The above named program is free software; you can redistribute it and/or
8// modify it under the terms of the GNU General Public
9// License version 2 as published by the Free Software Foundation.
10//
11// The above named program is distributed in the hope that it will be
12// useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
13// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14// General Public License for more details.
15//
16// You should have received a copy of the GNU General Public
17// License along with this work; if not, write to the Free Software
18// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
19//
20// ========== Copyright Header End ============================================
21/*
22 * Copyright (C) 1991, 2001, 2005 Sun Microsystems, Inc.
23 * All rights reserved.
24 */
25#pragma ident "@(#)1.4 02/05/2002 dr.cc"
26
27/*
28 * Copyright (c) 1989, Sun Microsystems, Inc. All Rights Reserved. Sun
29 * considers its source code as an unpublished, proprietary trade secret, and
30 * it is available only under strict license provisions. This copyright
31 * notice is placed here only to protect Sun in the event the source is
32 * deemed a published work. Disassembly, decompilation, or other means of
33 * reducing the object code to human readable form is prohibited by the
34 * license agreement under which this code is provided to the user or company
35 * in possession of this copy
36 *
37 * RESTRICTED RIGHTS LEGEND: Use, duplication, or disclosure by the
38 * Government is subject to restrictions as set forth in subparagraph
39 * (c) (1) (ii) of the Rights in Technical Data and Computer Software clause
40 * at DFARS 52.227-7013 and in similar clauses in the FAR and NASA FAR
41 * Supplement
42 */
43
44
45#include <sys/types.h>
46#include <sys/stat.h>
47#include <assert.h>
48#include <stdio.h>
49#include <stdlib.h>
50#include <errno.h>
51#include <string.h>
52#include <synch.h>
53
54#include "types.h"
55#include "dr.h"
56#include "system.h"
57#include "workerthread.h"
58#include "blaze_globals.h"
59
60#include "ui.h"
61
62///////////////////////////////////////////////////
63//
64// This module is an implementation of
65// BLAZE DUMP/RESTORE facility
66//
67///////////////////////////////////////////////////
68
69#include "dr_impl.h"
70
71static DR_unitNode *dr_head = NULL, *dr_tail = NULL;
72
73static char help_string [] = "dump <directory name> - directory shouldn't exist";
74static char *dr_dir = NULL;
75
76int dump_cmd_action (void*, int argc, char **argv);
77bool_t dump_blaze (DR_unit*);
78bool_t restore_blaze (DR_unit*);
79
80char ver[128] = BLAZEVERSION_STRING;
81char second_ver[128] = "\0";
82
83///////////////////////////////////////////////////
84
85int dump_version()
86{int ver_no, sub_ver_no; char blaze_ver[8];
87 strncpy(blaze_ver, ver ,4);
88 sscanf(blaze_ver, "%d.%d", &ver_no, &sub_ver_no);
89 return ver_no;
90}
91
92// This must be called in company with restore_v4_dump()!!
93int v4_sub_version()
94{int ver_no, sub_ver_no; char blaze_ver[8];
95 assert(restore_v4_dump());
96 if (handle_pseud_v4_dump())
97 strncpy(blaze_ver, second_ver, 4);
98 else
99 strncpy(blaze_ver, ver, 4);
100 sscanf(blaze_ver, "%d.%d", &ver_no, &sub_ver_no);
101 return sub_ver_no;
102}
103
104int sub_version()
105{int ver_no, sub_ver_no; char blaze_ver[8];
106 strncpy(blaze_ver, ver, 4);
107 sscanf(blaze_ver, "%d.%d", &ver_no, &sub_ver_no);
108 return sub_ver_no;
109}
110
111int sub_sub_version()
112{int ver_no, sub_ver_no, sub_sub_ver_no; char blaze_ver[8];
113 strncpy(blaze_ver, ver, 7);
114 sscanf(blaze_ver, "%d.%d.%d", &ver_no, &sub_ver_no, &sub_sub_ver_no);
115 return sub_sub_ver_no;
116}
117
118// For handling a primary V5 dump created from a restored V4 dump
119bool_t handle_pseud_v4_dump()
120{
121 if (second_ver[0] == '4')
122 return TRUE;
123 else
124 return FALSE;
125}
126
127bool_t restore_pure_v4_dump()
128{
129 if (BLAZE_restore_from_checkpoint() && dump_version() == 4)
130 return TRUE;
131 else
132 return FALSE;
133}
134
135bool_t restore_v4_dump()
136{
137 if (BLAZE_restore_from_checkpoint() && (dump_version() == 4 || handle_pseud_v4_dump()))
138 return TRUE;
139 else
140 return FALSE;
141}
142
143bool_t restore_v5_dump()
144{
145 if (BLAZE_restore_from_checkpoint() && dump_version() >= 5)
146 return TRUE;
147 else
148 return FALSE;
149}
150
151// ----------------------------------------------------------------------------
152//
153
154void init_dr ()
155{
156 //@@@ this is grotesque,
157 //@@@ why not call DR_register(&dump_blaze,&restore_blaze)
158
159 DR_unit *pdr;
160
161 dr_head = DR_unitNode::CreateInstance ("DR list");
162 dr_tail = dr_head;
163
164 if (dr_head == NULL) {
165 ui->error("Unable to allocate memory for DR");
166 return;
167 }
168 pdr = dr_head->GetData ();
169
170 pdr->dump_fn = dump_blaze; /* local ftn, calls SYSTEM_dump */
171 pdr->restore_fn = restore_blaze; /* local ftn, calls SYSTEM_restore */
172
173 pdr->name = (char*)strdup(BLAZE_SYSTEM);
174
175
176
177 UI_register_cmd_2 ((char*)"dump", help_string, dump_cmd_action, NULL);
178}
179
180
181
182
183// ----------------------------------------------------------------------------
184//
185// the "dump" UI command
186
187int dump_cmd_action (void*, int argc, char **argv)
188{
189 DR_unit *pdr;
190 DR_unitNode *pnode;
191
192 if (dump_version() < 5) {
193 ui->warning("restored from old-format (V4) dump; the new dump will be V5 format\n");
194 }
195
196 //** pre-dump criteria *****
197
198 if (!SYSTEM_is_stopped ()) {
199 ui->error("SAM must be STOPPED for dump");
200 return 1;
201 }
202
203
204 if (argc != 2) {
205 ui->error("Illegal UI command format ");
206 return 1;
207 }
208 if (mkdir(argv[1], S_IRWXU | S_IRWXG | S_IRWXO) == -1) {
209 ui->perror (argv[1]);
210 return 1;
211 }
212 ui->output("dump directory <%s> is created\n", argv[1]);
213
214
215
216
217 //** pre-dump actions *****
218
219 WorkerThread::doEventqueUnloads ();
220
221
222
223 //** now call every registered dump function *****
224
225 pdr = dr_head->GetData ();
226 pdr->dir = (char*)strdup(argv[1]);
227 dr_dir = (char*)strdup(argv[1]);
228
229 for (pnode = dr_head; pnode; pnode = pnode->Next()) {
230 pdr = pnode->GetData ();
231 if (pdr->dump_fn) {
232 ui->output("Dumping <%s> ...\n", pdr->name);
233
234 bool tmp = pdr->dump_fn(pdr); //*** <--- here's the action
235
236 ui->output(" %s\n",(tmp ? "done" : "failed"));
237 }
238 else {
239 ui->output("no dump action found for <%s> \n", pdr->name);
240 }
241 }
242
243 //** post-dump return *****
244
245 return 0;
246}
247
248
249// ----------------------------------------------------------------------------
250//
251// gets called indirectly by the above (dump_cmd_action) function
252//
253
254bool_t dump_blaze (DR_unit* pdr)
255{
256 char cmd_line[1024];
257 char *dumpfile = (char*) malloc (strlen(pdr->dir) + 64);
258
259 if (dumpfile == NULL) {
260 ui->error("memory problems");
261 return FALSE;
262 }
263
264 sprintf(cmd_line, "cp %s %s/%s", get_script_file(), pdr->dir, RC_DUMP);
265 if (system(cmd_line)) {
266 ui->error("Script copy failed. %s!", strerror(errno));
267 return FALSE;
268 }
269
270
271 sprintf (dumpfile, SAM_VERSION_FILE, pdr->dir);
272 pdr->fp = fopen(dumpfile, "w");
273 if (pdr->fp == NULL) {
274 ui->perror (dumpfile);
275 return FALSE;
276 }
277 fputs (SYSTEM_get_version(), pdr->fp);
278 fclose (pdr->fp);
279
280/* dump_version() < 5 means the restored V4 dump is being dumped as a V5 dump.
281 handle_pseud_v4_dump() means the V4 mixed V5 dump is being dumped again. */
282 if (dump_version() < 5 || handle_pseud_v4_dump()) {
283 sprintf (dumpfile, SECONDARY_VERSION_FILE, pdr->dir);
284 pdr->fp = fopen(dumpfile, "w");
285 if (pdr->fp == NULL) {
286 ui->perror (dumpfile);
287 return FALSE;
288 }
289 if (dump_version() < 5)
290 fputs(ver, pdr->fp);
291 else
292 fputs(second_ver, pdr->fp);
293 fclose (pdr->fp);
294 }
295
296
297 sprintf (dumpfile, "%s/%s.dmp", pdr->dir, pdr->name);
298 pdr->fp = fopen(dumpfile, "w");
299 if (pdr->fp == NULL) {
300 ui->perror (dumpfile);
301 return FALSE;
302 }
303 pdr->filename = (char*)strdup(dumpfile);
304
305 SYSTEM_dump (pdr->fp); //*** <--- here's the action, but this is
306 // only for "dump/blaze_system.dmp" !!!
307
308 fclose (pdr->fp);
309 return TRUE;
310}
311
312
313
314
315
316// ---------------------------------------------------------------------------
317//
318// gets called indirectly by ui_cmds.cc before first "run" command:
319// (@@@@@ but not for "stepi", "stepc" commands ?????)
320//
321// -> complete_initialization
322// -> restore_devices_action
323// -> DR_restore_object
324//
325
326bool_t restore_blaze (DR_unit* pdr)
327{
328 FILE *fp;
329 bool_t ret;
330 char *rfile = (char*) malloc (strlen(pdr->restore_dir) + strlen(pdr->name) + 16);
331
332
333 if (rfile == NULL) {
334 ui->error("memory problems");
335 return FALSE;
336 }
337
338 sprintf (rfile, "%s/%s.dmp", pdr->restore_dir, pdr->name);
339 fp = fopen(rfile, "r");
340 if (fp == NULL) {
341 ui->perror (rfile);
342 return FALSE;
343 }
344
345 ret = SYSTEM_restore (fp); //*** <--- here's the action, but this is
346 // only for "dump/blaze_system.dmp" !!!
347
348 fclose (fp);
349 return ret;
350}
351
352
353
354
355
356
357
358///////////////////////////////////////////////////
359
360void DR_register (const char *name, dump_action dump_fn, restore_action restore_fn, void * client_data)
361{
362
363 DR_unitNode *pnode = DR_unitNode::CreateInstance ("DR list");
364 DR_unit *pdr;
365
366 if (pnode == NULL) {
367 ui->error("unable to allocate memory for <%s>", name);
368 }
369 else {
370 pdr = pnode->GetData();
371 pdr->name = (char*) strdup (name);
372 pdr->dump_fn = dump_fn;
373 pdr->restore_fn = restore_fn;
374 pdr->client_data = client_data;
375
376 DR_unitNode::AddTail (&dr_head, &dr_tail, pnode);
377
378 }
379 return;
380}
381
382///////////////////////////////////////////////////
383
384void DR_unregister (void *client_data)
385{
386 DR_unitNode *pnode = dr_head;
387 DR_unitNode *prev = NULL;
388
389 while (pnode) {
390 DR_unit *pdr = pnode->GetData();
391
392 if (pdr->client_data == client_data) {
393 DR_unitNode::DeleteNode(&dr_head, prev);
394 prev = NULL;
395 pnode = dr_head;
396 }
397 else {
398 prev = pnode;
399 pnode = pnode->Next();
400 }
401 }
402}
403
404///////////////////////////////////////////////////
405
406char * DR_get_name (DR_OPAQUE pdr)
407{
408 return pdr->name;
409}
410
411char * DR_get_dir ()
412{
413 return dr_dir;
414}
415
416char * DR_get_rdir (DR_OPAQUE pdr)
417{
418 return pdr->restore_dir;
419}
420
421///////////////////////////////////////////////////
422
423void* DR_get_client_data (DR_OPAQUE pdr)
424{
425 return pdr->client_data;
426}
427
428///////////////////////////////////////////////////
429
430bool_t
431DR_restore_object (char * dir, char * name)
432{
433
434 DR_unitNode *pnode = dr_head;
435 DR_unit *pdr;
436 bool_t ret;
437
438 ui->output("Restoring <%s> ...", name);
439
440 for (;pnode; pnode = pnode->Next()) {
441 pdr = pnode->GetData();
442 if (strcmp(pdr->name, name) == NULL) {
443 pdr->restore_dir = (char*)strdup(dir);
444 dr_dir = (char*)strdup(dir);
445 if (pdr->restore_fn) {
446
447 ret = pdr->restore_fn (pdr); //***
448
449 }
450 else {
451 ret = FALSE;
452 ui->output(" .. NO HANDLER .. ");
453 }
454 ui->output(" %s \n", ret ? "done" : "failed");
455 return ret;
456 }
457 }
458 ui->error("failed\n");
459 return FALSE;
460}
461
462
463//** if restoring, is called from UI before first "run" command
464//
465void restore_devices_action(char *dir)
466{
467 DR_unit *pdr;
468 DR_unitNode *pnode;
469
470 for (pnode = dr_head; pnode; pnode = pnode->Next()) {
471 pdr = pnode->GetData ();
472
473 if (!DR_restore_object(dir, pdr->name)) //***
474
475 exit(1);
476 }
477}