Commit | Line | Data |
---|---|---|
920dae64 AT |
1 | // ========== Copyright Header Begin ========================================== |
2 | // | |
3 | // OpenSPARC T2 Processor File: main.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) 1996, 2001 Sun Microsystems, Inc. | |
23 | * All rights reserved. | |
24 | */ | |
25 | #pragma ident "@(#)1.36 03/06/02 main.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 | /* standard C includes */ | |
45 | #include <assert.h> | |
46 | #include <errno.h> | |
47 | #include <fcntl.h> | |
48 | #include <stdio.h> | |
49 | #include <strings.h> | |
50 | #include <unistd.h> | |
51 | #include <dirent.h> | |
52 | #include <thread.h> | |
53 | #include <stdlib.h> | |
54 | #include <ctype.h> | |
55 | #include <limits.h> | |
56 | #include <netdb.h> | |
57 | #include <libgen.h> | |
58 | ||
59 | /* solaris includes */ | |
60 | #include <sys/types.h> | |
61 | #include <sys/stat.h> | |
62 | #include <sys/types.h> | |
63 | #include <sys/param.h> | |
64 | #include <sys/wait.h> | |
65 | #include <sys/regset.h> | |
66 | ||
67 | #include <signal.h> | |
68 | #include <siginfo.h> | |
69 | #include <ucontext.h> | |
70 | ||
71 | #include <dlfcn.h> | |
72 | ||
73 | #include <list> | |
74 | ||
75 | /* project includes */ | |
76 | #include "types.h" | |
77 | #include "blaze_globals.h" | |
78 | #include "sim_cmd_struct.h" | |
79 | #include "fileutil.h" | |
80 | #include "term.h" | |
81 | #include "system.h" | |
82 | #include "ui.h" | |
83 | #include "dr.h" | |
84 | ||
85 | typedef void* TM_OPAQUE_DATA; | |
86 | #include "tracemod.h" | |
87 | #include "ui_utils.h" | |
88 | #include "ui_cmds.h" | |
89 | #include "system_impl.h" | |
90 | ||
91 | #include "vtracer.h" | |
92 | #include "vtracer_async_queue.h" | |
93 | ||
94 | // Flexconfig | |
95 | #include "serial_mod.h" | |
96 | // to access serial device | |
97 | #include "property.h" | |
98 | #include "mmi.h" | |
99 | #include "remote.h" | |
100 | ||
101 | #include "dev_registry.h" | |
102 | ||
103 | ||
104 | #define DEFAULT_RC_FILE ".blazerc" | |
105 | int scsi_ctrl_count = 0; | |
106 | devRegistry * samDevs; | |
107 | uint64_t property_list::fkprom_dtinbuf_pa = 0x50; | |
108 | int property_list::fkprom_dtinbuf_offset = 0x0; | |
109 | ||
110 | vtracer_async_queue * trace_async_queue = NULL; | |
111 | ||
112 | ||
113 | /////////////////////////////////////////////// | |
114 | int blaze_debug = 0; | |
115 | int blaze_option = 0; | |
116 | /////////////////////////////////////////////// | |
117 | ||
118 | char version[] = BLAZEVERSION_STRING; // version.h | |
119 | //configstate_t *config_arch = NULL; | |
120 | ||
121 | ||
122 | /* */ | |
123 | volatile e_blaze_runstate_t blaze_run_state = e_BLAZE_INVALID; | |
124 | volatile int blaze_stop_request = 0; | |
125 | ||
126 | ||
127 | static int openasroot = 0; // open disk devs as root? | |
128 | ||
129 | int obp_boot_option = 0; // default to fakeprom | |
130 | ||
131 | ||
132 | /* Memory Object */ | |
133 | memT *mm1 = NULL; | |
134 | ||
135 | ||
136 | ||
137 | // this is the master clock // not a clock, is total of all cpus ! | |
138 | volatile uint64_t global_tick = 0; // should be in system.cc, be static | |
139 | ||
140 | /* For terminal output to a file */ | |
141 | ||
142 | typedef struct { | |
143 | char *configfile; | |
144 | std::list<char *> *execfiles; | |
145 | char *progname; | |
146 | char *logFileName; | |
147 | char *console_display_name; | |
148 | char *overlaydir; | |
149 | char *restore_dir; | |
150 | #define CMM_RESTORE 1 | |
151 | uint16_t cmdline_mode; | |
152 | bool_t immediate_start; | |
153 | bool_t no_startup; | |
154 | bool_t start_python; | |
155 | FILE *serial_output_file; | |
156 | char *serial_output_fname; | |
157 | FILE *scsi_conf_file; | |
158 | char *scsi_conf_fname; | |
159 | uint32_t tsync_port; | |
160 | ||
161 | } Blaze_cmd_opt; | |
162 | ||
163 | Blaze_cmd_opt *Popt = NULL; | |
164 | const char * overlaydir = NULL; | |
165 | ||
166 | ||
167 | ||
168 | archglobals_t volatile the_arch = { 0 }; | |
169 | archglobals_t the_arch_backup = { 0 }; | |
170 | ||
171 | volatile int64_t the_arch_cmips = 0; /* sw05b Hack */ | |
172 | volatile int the_arch_ccntx = 0; | |
173 | ||
174 | ||
175 | ||
176 | extern "C" { | |
177 | void sigcore_handler(int sig, siginfo_t *si, void *arg2); | |
178 | ||
179 | void sigignore_handler(int sig); | |
180 | void sigconfirm_handler(int sig); | |
181 | void sigtermination_handler(int sig); | |
182 | } | |
183 | ||
184 | static void init_devices(); | |
185 | ||
186 | static void copy_configuration(const archglobals_t& arch_src, | |
187 | archglobals_t *arch_dest); | |
188 | static void verify_configuration(const archglobals_t& arch_src, | |
189 | const archglobals_t& arch_dest); | |
190 | ||
191 | static void init_config_arch (); | |
192 | ||
193 | // FORWARD DECLARATIONS: | |
194 | bool_t vcpu_save(DR_OPAQUE pdr); | |
195 | bool_t vcpu_restore(DR_OPAQUE pdr); | |
196 | ||
197 | ||
198 | /* Externals */ | |
199 | extern void start_filecmd_check (SimCmd* state); | |
200 | int check_tick_cmpr; | |
201 | extern VCPU_ExInterface g_cpu_ex_intf; | |
202 | extern char cpu_lib_name[160]; | |
203 | ||
204 | /* | |
205 | * Major Paine Threads | |
206 | */ | |
207 | void sim_thread_loop (SimCmd*); | |
208 | ||
209 | #ifdef __cplusplus | |
210 | extern "C" { | |
211 | #endif | |
212 | void * term_thread_wrapper(void *); // simulated system console | |
213 | #ifdef __cplusplus | |
214 | } | |
215 | #endif | |
216 | ||
217 | // The -- option (or first non option) stops the blaze commandline | |
218 | // parsing and all remaining options are put into the app_argv | |
219 | // vector. These remaining options are passed on to the | |
220 | // python interpreter when it is loaded | |
221 | ||
222 | static int app_argc = 0; | |
223 | static char** app_argv = 0; | |
224 | ||
225 | /* | |
226 | * Handle Command Line Options | |
227 | * For getopt() library routine | |
228 | */ | |
229 | ||
230 | extern char *optarg; | |
231 | extern char ver[128]; | |
232 | extern char second_ver[128]; | |
233 | extern int optind; | |
234 | extern void* asi_ptr[]; | |
235 | ||
236 | Blaze_cmd_opt* handle_args(int argc, char **argv); | |
237 | static void print_banner(); | |
238 | ||
239 | const char* diskspecfile = "pcidisk.init"; | |
240 | static SimCmd command; | |
241 | static int not_root_warning = 0; | |
242 | ||
243 | char *pty_dev_a, *pty_dev_b; | |
244 | char *pty_dev_c, *pty_dev_d; | |
245 | ||
246 | char* console_display; | |
247 | bool pop_window = false; | |
248 | ||
249 | ||
250 | extern uint64_t get_page_mask(int); | |
251 | ||
252 | ||
253 | ||
254 | ||
255 | //////////////////////////////////////////////////////////// | |
256 | ||
257 | uint32_t BLAZE_restore_from_checkpoint () | |
258 | { | |
259 | return Popt->cmdline_mode & CMM_RESTORE; | |
260 | } | |
261 | ||
262 | void get_dump_version() | |
263 | { | |
264 | int v, sv, ssv = 0; FILE *fp; char rfile[PATH_MAX]; | |
265 | ||
266 | sprintf (rfile, SAM_VERSION_FILE, get_restore_dir()); | |
267 | fp = fopen(rfile, "r"); | |
268 | if (!fp) { | |
269 | sprintf (rfile, BLAZE_VERSION_FILE, get_restore_dir()); | |
270 | fp = fopen(rfile, "r"); | |
271 | } | |
272 | if (!fp) { | |
273 | ui->warning("No SAM version is specified in the dump\n "); | |
274 | ui->warning("there is no guarantee of successfull restoration!!\n "); | |
275 | return; | |
276 | } else { | |
277 | if (fgets (ver, 120, fp) == NULL) | |
278 | ui->warning("CHECKPOINT might be corrupted!!\n "); | |
279 | else | |
280 | ui->output("CHECKPOINT of SAM v %s\n ", ver); | |
281 | fclose (fp); | |
282 | } | |
283 | ||
284 | sprintf (rfile, SECONDARY_VERSION_FILE, get_restore_dir()); | |
285 | fp = fopen(rfile, "r"); | |
286 | if (fp) { | |
287 | if (fgets (second_ver, 120, fp) == NULL) | |
288 | ui->warning("Secondary V4 dump info lost!\n "); | |
289 | else | |
290 | ui->output("Secondary V4 version: %s\n ", second_ver); | |
291 | fclose (fp); | |
292 | } | |
293 | ||
294 | if (strcmp(DEFAULT_RC_FILE, Popt->configfile)) | |
295 | return; // specified by '-c' already | |
296 | ||
297 | sscanf(ver, "%d.%d.%d", &v, &sv, &ssv); | |
298 | if (v > 5 || v == 5 && sv >= 5) { | |
299 | sprintf(rfile, "%s/%s", get_restore_dir(), RC_DUMP); | |
300 | if (isFile((const char *)rfile)) | |
301 | Popt->configfile = (char*)strdup(rfile); | |
302 | } | |
303 | ||
304 | if (!isFile(Popt->configfile)) { | |
305 | ui->error("No script file for restoring!\n"); | |
306 | exit(-1); | |
307 | } | |
308 | } | |
309 | ||
310 | char *get_script_file() | |
311 | { | |
312 | return Popt->configfile; | |
313 | } | |
314 | ||
315 | char *get_restore_dir() | |
316 | { | |
317 | return Popt->restore_dir; | |
318 | } | |
319 | ||
320 | //////////////////////////////////////////////////////////// | |
321 | ||
322 | serialInterface * systemConsole; // system console pointer | |
323 | ||
324 | int access_serial_cb | |
325 | ( | |
326 | uint8_t *c, // character to read/write | |
327 | int wr // 0 - read, 1 - write | |
328 | ) | |
329 | { | |
330 | ||
331 | if(systemConsole == 0){ | |
332 | ui->error("systemConsole pointer null. Possible configuration problem!!\n"); | |
333 | exit(0); | |
334 | } | |
335 | ||
336 | if (wr == 0) // read | |
337 | { | |
338 | LWord buf = 0; | |
339 | ||
340 | /* Write the intent of READING the register 0x0 */ | |
341 | systemConsole->reg_access( (char *)&buf, PORT_A_CONTROL, 0x1); | |
342 | ||
343 | /* Read the register that the SERIAL CONTROL REGISTER is pointing to */ | |
344 | systemConsole->reg_access( (char *)&buf, PORT_A_CONTROL, 0x0); | |
345 | ||
346 | /* If data is available */ | |
347 | if (buf & RX_CHAR_AVAILABLE) | |
348 | { | |
349 | /* Read the port register */ | |
350 | systemConsole->reg_access((char *)&buf, PORT_A_DATA, 0x0); | |
351 | } | |
352 | else // no data available | |
353 | { | |
354 | buf = 0xff; | |
355 | } | |
356 | *c = uint8_t(buf); // char read | |
357 | } | |
358 | else // write | |
359 | { | |
360 | LWord buf = (LWord)*c; | |
361 | systemConsole->reg_access((char *)&buf, PORT_A_DATA, 0x1); | |
362 | } | |
363 | ||
364 | return 0; | |
365 | } | |
366 | ||
367 | //////////////////////////////////////////////////////// | |
368 | int access_io_cb | |
369 | ( | |
370 | int cpuid, // cpu id | |
371 | int wr, // operation code | |
372 | uint64_t paddr, // physical address | |
373 | uint32_t size, // access size | |
374 | uint64_t &data, // 64 bit value to read/write | |
375 | uint64_t bitmask // access bit mask | |
376 | ) | |
377 | { | |
378 | return SYSTEM_physio_access ( cpuid, NULL, paddr, bool_t(wr), size, &data, uint8_t(bitmask) ); | |
379 | ||
380 | } | |
381 | ||
382 | //////////////////////////////////////////////////////// | |
383 | int access_asi_cb | |
384 | ( | |
385 | int sid, // cpu id | |
386 | int operation, // operation code | |
387 | uint32_t asi, // asi value | |
388 | uint64_t vaddr, // virtual address | |
389 | int32_t size, // access size | |
390 | uint64_t &buf // 64 bit data value | |
391 | ) | |
392 | { | |
393 | int rc; | |
394 | ||
395 | // loadable modules that implement external asi should be | |
396 | // thread safe | |
397 | if ((operation == VCPU_LOAD_OP)) { | |
398 | rc = TM_execute_load_asi (asi, vaddr, &buf, size, sid); | |
399 | } | |
400 | else { // operation == store | |
401 | rc = TM_execute_store_asi (asi, vaddr, &buf, size, sid); | |
402 | } | |
403 | ||
404 | return rc; | |
405 | } | |
406 | ||
407 | ||
408 | ||
409 | ||
410 | /////////////////////////////////// | |
411 | // | |
412 | // CPU initialization | |
413 | // | |
414 | Vcpu * init_cpu ( char *path, int argc, char **argv) | |
415 | { | |
416 | ||
417 | int id = g_nvcpu; | |
418 | ||
419 | VCPU_Config config_info; // cpu config params | |
420 | ||
421 | // set defaullt values | |
422 | set_default ( config_info ); | |
423 | ||
424 | ||
425 | // parse configuration parameters | |
426 | if ( argc > 0 ) | |
427 | { | |
428 | for ( int i=0; i<argc; i++) | |
429 | { | |
430 | if ( set_param ( argv[i], &config_info ) != 0) | |
431 | { | |
432 | ui->error("cannot set cpu param %s\n", argv[i]); | |
433 | exit (1); | |
434 | } | |
435 | ||
436 | } | |
437 | } | |
438 | ||
439 | ||
440 | // system interface for the cpu module | |
441 | VCPU_ImpIntf sys_intf; | |
442 | sys_intf.access_io = access_io_cb; | |
443 | sys_intf.access_serial = access_serial_cb; | |
444 | sys_intf.access_asi = access_asi_cb; | |
445 | sys_intf.vtrace = NULL; //instruction_cb; | |
446 | sys_intf.mem = mm1; // sys mem | |
447 | ||
448 | Vcpu* vcpu = create_cpu ( path, config_info, &sys_intf ); | |
449 | ||
450 | if (vcpu == NULL) | |
451 | { | |
452 | ui->error( "FATAL : unable to create CPU %d \n", | |
453 | id); | |
454 | exit (1); | |
455 | } | |
456 | ||
457 | // for compatibility with v4 dump/restore skip "blaze" cpu model | |
458 | if ((id == 0) && ((vcpu->config.cpu_type & VCPU_IMPL_SIM_MASK) != VCPU_IMPL_SIM_BLAZE)) | |
459 | { | |
460 | DR_register( (char*)"cpu", vcpu_save, vcpu_restore, vcpu ); | |
461 | } | |
462 | ||
463 | ||
464 | if (trace_async_queue == NULL) { | |
465 | trace_async_queue = new vtracer_async_queue; | |
466 | } | |
467 | ||
468 | return vcpu; | |
469 | } | |
470 | ||
471 | ////////////////////////////////////////////////// | |
472 | // | |
473 | // save a vcpu (for dump/restore) | |
474 | // | |
475 | bool_t vcpu_save(DR_OPAQUE pdr) | |
476 | { | |
477 | char *dir = DR_get_dir(); | |
478 | return g_cpu_ex_intf.save(dir); | |
479 | } | |
480 | ||
481 | ////////////////////////////////////////////////// | |
482 | // | |
483 | // restore a vcpu (for dump/restore) | |
484 | // | |
485 | bool_t vcpu_restore(DR_OPAQUE pdr) | |
486 | { | |
487 | char *dir = DR_get_rdir (pdr); | |
488 | return g_cpu_ex_intf.restore(dir); | |
489 | return FALSE; | |
490 | } | |
491 | ||
492 | ||
493 | ////////////////////////////////////////////////// | |
494 | // | |
495 | // Creates TERMINAL/CONSOLE Thread | |
496 | // | |
497 | void init_threads () | |
498 | { | |
499 | #ifdef V5_FAKEPROM | |
500 | thread_t termThread; // special thread that handles terminal IO | |
501 | ||
502 | ||
503 | thr_create(NULL, NULL, term_thread_wrapper, NULL, | |
504 | THR_BOUND|THR_DAEMON, &termThread); | |
505 | #endif | |
506 | } | |
507 | ||
508 | ////////////////////////////////////////////////// | |
509 | ||
510 | extern int term_console (char *pty_dev, char *display); | |
511 | ||
512 | #ifdef BS_WRAPPER | |
513 | #ifdef __cplusplus | |
514 | extern "C" { | |
515 | #endif | |
516 | extern void init_simix(); | |
517 | #ifdef __cplusplus | |
518 | } | |
519 | #endif | |
520 | #endif | |
521 | ||
522 | ||
523 | ||
524 | ||
525 | ||
526 | /* ------------------------------------------------------------------------ | |
527 | * blaze signal handlers | |
528 | * | |
529 | * whats weird about unix/posix/solaris signal handlers is that they are | |
530 | * process-wide, you cannot have a different handler for each thread, | |
531 | * so we register all signal handlers here... | |
532 | * (you can block/unblock signals on a per-thread basis, which we do, | |
533 | * and which is done inside each thread separately as necessary). | |
534 | * | |
535 | */ | |
536 | void init_signal_handlers () | |
537 | { | |
538 | /***** core dump signals **************** SIGBUS, SIGSEGV, SIGILL ******/ | |
539 | struct sigaction sact; | |
540 | sact.sa_handler = NULL; | |
541 | sact.sa_sigaction = sigcore_handler; | |
542 | sact.sa_flags = SA_SIGINFO | SA_RESETHAND; | |
543 | sigaction(SIGBUS, &sact, NULL); | |
544 | sigaction(SIGSEGV, &sact, NULL); | |
545 | sigaction(SIGILL, &sact, NULL); | |
546 | ||
547 | /***** must ignore signals ********************* SIGPIPE, SIGUSR1 ******/ | |
548 | // must ignore sigpipe or blaze will crash whenever switchsim does | |
549 | signal (SIGPIPE, sigignore_handler); | |
550 | // for unsticking blaze threads that are stuck in blocking IO | |
551 | // for terminating workerthreads so we can reconfigure | |
552 | signal (SIGUSR1, sigignore_handler); /* disconnect (and park) rcvr-thread */ | |
553 | signal (SIGINT, sigignore_handler); /* kill worker-thread */ | |
554 | ||
555 | /***** special case signals ********************* SIGINT, SIGQUIT ******/ | |
556 | /* signal handler for blaze-keyboard -> ask for user confirmation */ | |
557 | // be user friendly, don't let accidental ctrl-C kill blaze !!! | |
558 | signal (SIGINT, sigconfirm_handler); /* BREAK */ | |
559 | signal (SIGQUIT, sigconfirm_handler); /* CTRL-C */ | |
560 | /*signal (SIGHUP, sigconfirm_handler); * HangUp */ | |
561 | ||
562 | // we're still not sure what this means or what to do when it happens... | |
563 | // /* signal handler for blaze-nonmaskable-termination -> ? */ | |
564 | // // graceful shutdown before nonmaskable kill signal ??? | |
565 | signal (SIGTERM, sigtermination_handler); | |
566 | ||
567 | } // ----------------------------------------------------------------------- | |
568 | ||
569 | ||
570 | // Search for $SAM/etc/<proc>_samrc and add it to the Popt->execfiles list | |
571 | static void samrc_init() { | |
572 | if (g_nvcpu != 0) { | |
573 | Vcpu *vcpu = g_vcpu[0]; | |
574 | const char *cpu_name = vcpu->cpu_name(vcpu->config.cpu_type); | |
575 | const char* exec_name = getexecname(); | |
576 | char* sam_dir = NULL; | |
577 | if (exec_name == NULL || | |
578 | (sam_dir = strdup(exec_name)) == NULL || | |
579 | (sam_dir = dirname(sam_dir)) == NULL) { | |
580 | ui->error("can't allocate memory while searching for " | |
581 | "$SAM/bin/sam\n", cpu_name); | |
582 | return; | |
583 | } | |
584 | ||
585 | // Here sam_dir should point to $SAM/bin; check to make sure. | |
586 | int sam_dir_len = strlen(sam_dir); | |
587 | if (strcmp(&sam_dir[sam_dir_len - 4], "/bin") != 0) { | |
588 | ui->error("Non-standard sam installation; aborting " | |
589 | "search for $SAM/etc/%s_samrc\n", cpu_name); | |
590 | return; | |
591 | } | |
592 | sam_dir[sam_dir_len - 4] = '\0'; // Make sam-dir -> $SAM | |
593 | ||
594 | // Allocate space for "$SAM/etc/<proc>_samrc" and use sprintf | |
595 | // to assign it. | |
596 | char *samrc_name = | |
597 | (char *)malloc(sam_dir_len + sizeof("/etc/_samrc") + | |
598 | strlen(cpu_name)); | |
599 | if (samrc_name == NULL) { | |
600 | ui->error("can't allocate memory while searching for " | |
601 | "$SAM/etc/%s_samrc\n", cpu_name); | |
602 | return; | |
603 | } | |
604 | sprintf(samrc_name, "%s/etc/%s_samrc", sam_dir, cpu_name); | |
605 | ||
606 | // If the <proc>_samrc file exists, prepend it to the list of files | |
607 | // to execute at start up. | |
608 | struct stat stat_buf; | |
609 | if (stat(samrc_name, &stat_buf) != -1) | |
610 | Popt->execfiles->push_front(samrc_name); | |
611 | } | |
612 | } | |
613 | ||
614 | ||
615 | static bool sysconf_done = false; | |
616 | ||
617 | bool SYSTEM_sysconf_done() { return sysconf_done; } | |
618 | ||
619 | // called after last sysconf line in RC file has been parsed. | |
620 | ||
621 | static void complete_initialization() | |
622 | { | |
623 | if (!sysconf_done) { | |
624 | SYSTEM_init(); | |
625 | TM_module_init(); // report MMI_CONFIG_INIT_DONE | |
626 | if (BLAZE_restore_from_checkpoint()) { | |
627 | restore_devices_action(get_restore_dir()); | |
628 | ui->output("----- RESTORE COMPLETED -----\n"); | |
629 | } | |
630 | samrc_init(); | |
631 | sysconf_done = true; | |
632 | } | |
633 | } | |
634 | ||
635 | static void process_rc_file(const char * fn){ | |
636 | ||
637 | FILE * fp = fopen(fn,"r"); | |
638 | if( !fp ){ | |
639 | ui->error("Can not open SAM RC file %s\n",fn); | |
640 | exit(1); | |
641 | } | |
642 | const int max_buf_size = 1024 * 10; | |
643 | char buf[max_buf_size]; | |
644 | int buf_index = 0; | |
645 | ||
646 | // find the line number of last uncommented sysconf in RC file | |
647 | // this assumes that all conf's, loads are before last sysconf. | |
648 | ||
649 | // XXX : to be removed if -f <filename> becomes the norm | |
650 | ||
651 | int line = 0; int cntr = 0; | |
652 | while(fgets(buf,max_buf_size,fp)){ | |
653 | cntr++; | |
654 | buf_index = 0; | |
655 | while(buf[buf_index] && isspace(buf[buf_index])) | |
656 | buf_index++; | |
657 | ||
658 | if(buf[buf_index] == '#') | |
659 | continue; // skip comment line | |
660 | ||
661 | if(!strncmp("sysconf",buf + buf_index,strlen("sysconf")) \ | |
662 | && isspace( *(buf+buf_index + strlen("sysconf")) )) | |
663 | line = cntr; | |
664 | ||
665 | } | |
666 | ||
667 | fseek(fp,0,SEEK_SET); | |
668 | ||
669 | cntr = 0; | |
670 | while(fgets(buf,max_buf_size,fp)){ | |
671 | UI_exec_cmd(buf); | |
672 | cntr++; | |
673 | if(cntr == line) | |
674 | complete_initialization(); | |
675 | } | |
676 | ||
677 | fclose(fp); | |
678 | ||
679 | return; | |
680 | } | |
681 | ||
682 | // -f <filename> SAM command line option | |
683 | static void process_command_file(const char * fn){ | |
684 | ||
685 | FILE * fp = fopen(fn,"r"); | |
686 | if( !fp ){ | |
687 | ui->error("Can not open SAM command file %s\n",fn); | |
688 | exit(1); | |
689 | } | |
690 | const int max_buf_size = 1024 * 10; | |
691 | char buf[max_buf_size]; | |
692 | char buf_index = 0; | |
693 | ||
694 | // make sure that there are no sysconf's in the command file | |
695 | // make sure that there are no conf's in the command file | |
696 | int sysconf_line = -1; int conf_line = -1; int cntr = 0; | |
697 | while(fgets(buf,max_buf_size,fp)){ | |
698 | cntr++; | |
699 | buf_index = 0; | |
700 | while(buf[buf_index] && isspace(buf[buf_index])) | |
701 | buf_index++; | |
702 | ||
703 | if(buf[buf_index] == '#') | |
704 | continue; // comment line | |
705 | if(!strncmp("sysconf",buf + buf_index,strlen("sysconf")) \ | |
706 | && isspace( *(buf+buf_index + strlen("sysconf")) )){ | |
707 | sysconf_line = cntr; | |
708 | break; | |
709 | } | |
710 | if(!strncmp("conf",buf + buf_index,strlen("conf")) \ | |
711 | && isspace( *(buf+buf_index + strlen("conf")) )){ | |
712 | conf_line = cntr; | |
713 | break; | |
714 | } | |
715 | } | |
716 | ||
717 | if(sysconf_line != -1){ | |
718 | ui->error("command file %s has sysconf directive\n",fn); | |
719 | exit(1); | |
720 | } | |
721 | fseek(fp,0,SEEK_SET); | |
722 | while(fgets(buf,max_buf_size,fp)){ | |
723 | UI_exec_cmd(buf); | |
724 | } | |
725 | return; | |
726 | } | |
727 | ||
728 | extern void ui_readline(); | |
729 | ||
730 | int main (int argc, char **argv) | |
731 | { | |
732 | init_SYSTEM_open (); // sets up search path for "load" ui cmds | |
733 | ||
734 | for (int i=0; i<MAX_MP; i++) cpu_enabled[i] = 1; | |
735 | cpu_enable_changed = 1; | |
736 | ||
737 | init_signal_handlers (); | |
738 | ||
739 | // | |
740 | // Rummage up some additional file descriptors | |
741 | // | |
742 | struct rlimit rl; | |
743 | getrlimit(RLIMIT_NOFILE, &rl); | |
744 | rl.rlim_cur = rl.rlim_max; | |
745 | setrlimit(RLIMIT_NOFILE, &rl); | |
746 | ||
747 | // | |
748 | // get command line arguments | |
749 | // | |
750 | Popt = handle_args (argc,argv); | |
751 | ||
752 | // | |
753 | // to setup some necessary default values in THE_ARCH | |
754 | // | |
755 | init_config_arch(); | |
756 | print_banner(); | |
757 | ||
758 | char *rdt_name = term_redirect_get_file (); | |
759 | if (rdt_name) { | |
760 | ui->output("console input redirected from <%s> \n", rdt_name); | |
761 | } | |
762 | ||
763 | // | |
764 | // logging/debugging initialization | |
765 | // | |
766 | if (Popt->logFileName) | |
767 | { | |
768 | FILE* logfile; | |
769 | if ((logfile = fopen(Popt->logFileName, "w+")) == NULL) { | |
770 | ui->error("Unable to open log file <%s>", Popt->logFileName); | |
771 | exit(1); | |
772 | } | |
773 | ui->set_log_file(logfile); | |
774 | } | |
775 | ||
776 | // Get dump version for the requirement of some constructors of device modules. | |
777 | if (BLAZE_restore_from_checkpoint()) | |
778 | get_dump_version(); | |
779 | ||
780 | // to prepare for UI command registering | |
781 | preinit_ui (); | |
782 | ||
783 | // init loadable module support | |
784 | init_tm (); | |
785 | ||
786 | // | |
787 | // dump/restore initialization, before UI thread initiated. | |
788 | // | |
789 | init_dr (); | |
790 | init_threads(); // includes all CPU related threads start | |
791 | init_devices(); | |
792 | ||
793 | samDevs = new devRegistry(); | |
794 | ||
795 | // process the configeRC file before starting the UI thread | |
796 | process_rc_file(Popt->configfile); | |
797 | ||
798 | SYSTEM_unlock(); | |
799 | ||
800 | init_ui (Popt->configfile, TRUE); | |
801 | ||
802 | // Load python if user specified -py | |
803 | if(Popt->start_python) { | |
804 | std::string cmd = "run-python-file"; | |
805 | if (app_argc) { | |
806 | for (int i=0; i< app_argc; i++) | |
807 | { | |
808 | cmd += ' '; | |
809 | cmd += app_argv[i]; | |
810 | } | |
811 | } else { | |
812 | // no python application specified, load dummy | |
813 | cmd += " /dev/null"; | |
814 | } | |
815 | cmd += '\n'; | |
816 | UI_exec_cmd((char*)cmd.c_str()); | |
817 | } | |
818 | ||
819 | // check to see if there is -f <filename> option provided | |
820 | // if yes, execute the UI commands in there | |
821 | for (std::list<char*>::iterator iter = Popt->execfiles->begin(); | |
822 | iter != Popt->execfiles->end(); | |
823 | ++iter) { | |
824 | process_command_file(*iter); | |
825 | } | |
826 | ||
827 | // Jump into the readline enabled ui handler. We exit | |
828 | // there on quit (or eof). | |
829 | ||
830 | ui_readline(); | |
831 | ||
832 | // just wait for all child threads (CPU, I/O, net, UI) to complete | |
833 | while (thr_join(0, NULL, NULL) == 0 ) { | |
834 | ;//sleep(1); ** no reason to sleep, thr_join will select a thrd ** | |
835 | } | |
836 | ||
837 | ui->fatal("unexpected termination!!! \n"); | |
838 | return 0; | |
839 | } | |
840 | ||
841 | ||
842 | ||
843 | //////////////////////////////////////////////////////// | |
844 | ||
845 | void init_devices() | |
846 | { | |
847 | int serial_dev_no = 0; | |
848 | ||
849 | int uid = getuid(); // me | |
850 | int euid = geteuid(); // root | |
851 | int status = seteuid(uid); // backdown from root | |
852 | ||
853 | // do not do it again in pcidisk.cc | |
854 | ui->verbose("For all disks : overlay directory is <%s> \n", Popt->overlaydir); | |
855 | overlaydir = (char*)strdup(Popt->overlaydir); | |
856 | ||
857 | } // init_devices() | |
858 | ||
859 | ||
860 | ////////////////////////////////////////////////// | |
861 | ||
862 | static void init_config_arch () { | |
863 | ||
864 | the_arch.nwins = 8; | |
865 | #ifdef CHPLUS | |
866 | the_arch.mmutype = (char*)strdup("cheetahplus"); | |
867 | #else | |
868 | the_arch.mmutype = (char*)strdup("cheetah"); | |
869 | #endif | |
870 | the_arch.tlbsize = 64; | |
871 | the_arch.numcpus = 1; | |
872 | the_arch.loopticks = 16; | |
873 | the_arch.stickincr = 1; | |
874 | the_arch.cpus_per_thread = -1; | |
875 | the_arch.numthreads = -1; | |
876 | the_arch.arch_flags = 0; | |
877 | the_arch.skip_mp = 10; | |
878 | the_arch.block_mp = 0; | |
879 | the_arch.cpi = FALSE; | |
880 | ||
881 | } | |
882 | ||
883 | // | |
884 | // make a copy of the original config.init values | |
885 | // | |
886 | static void | |
887 | copy_configuration(const archglobals_t& arch_src, | |
888 | archglobals_t *arch_dest) | |
889 | { | |
890 | // first do a bit-by-bit copy | |
891 | memcpy((void *)arch_dest, (const void *)&arch_src, sizeof(archglobals_t)); | |
892 | // then do a real copy on string | |
893 | arch_dest->mmutype = strdup(arch_src.mmutype); | |
894 | } | |
895 | ||
896 | ||
897 | // | |
898 | // comapre the configuration values in config.init with the newly | |
899 | // inputted values (from restore operation, e.g.) | |
900 | // | |
901 | static void | |
902 | verify_configuration(const archglobals_t& /* arch_src */, | |
903 | const archglobals_t& /* arch_dest */) | |
904 | { | |
905 | } | |
906 | ||
907 | ||
908 | void usage () { | |
909 | ||
910 | ui->output( | |
911 | "sam [-options]\n\n\ | |
912 | Version %s\n\ | |
913 | -h - this screen,\n\ | |
914 | -c CFILE - use configuration file CFILE (eg: -c sam.rc)\n\ | |
915 | -R path - restore from dump directory specified in <path>\n\ | |
916 | -goodtrap <pc> - (SAM-only) exit on this pc_va; return 0\n\ | |
917 | -badtrap <pc> - (SAM-only) exit on this pc_va; return 1\n\ | |
918 | -v(ersion) - print version and exit\n\ | |
919 | -w - start xterm window for sim console\n\ | |
920 | -y ovdir - put disk overlays in OVDIR (do not use /tmp for big files)\n\ | |
921 | -f <filename> - execute SAM UI commands in <filename> after RC file is processed\n\ | |
922 | -- <arg0> ... - start Pyhton if py does not occur in RC file, execute\n\ | |
923 | arg0 (if present) as script file passing other args as args to script file.\n\ | |
924 | If py specified in rc file, pass all arguments w/o interpretation to Python\n\ | |
925 | -l LFILE - use log file LFILE\n\ | |
926 | -obp - boot CH/CH+ SAM with COBP\n\ | |
927 | -nomemreserve - allocate simulated memory on demand. Only supported on builds with flat memory model. \n\ | |
928 | ", | |
929 | BLAZEVERSION_STRING); | |
930 | } | |
931 | ||
932 | //////////////////////////////////////////////////// | |
933 | ||
934 | ||
935 | static int | |
936 | StrEq(const char *s1, const char *s2) { | |
937 | if ( (s1==NULL) || (s2==NULL)) { | |
938 | return 0; | |
939 | } | |
940 | ||
941 | while(*s1 != 0) { | |
942 | if (*s1++ != *s2++) { | |
943 | return NULL; | |
944 | } | |
945 | } | |
946 | return (*s2 == 0); | |
947 | } // StrEq() | |
948 | ||
949 | ||
950 | #define TSYNC_PORT 11000 | |
951 | ||
952 | ||
953 | // | |
954 | // Handle Command Line options | |
955 | // | |
956 | ||
957 | Blaze_cmd_opt * | |
958 | handle_args (int argc, char **argv) | |
959 | { | |
960 | ||
961 | char hostname[MAXHOSTNAMELEN]; | |
962 | char ovd[MAXHOSTNAMELEN + 64]; | |
963 | Blaze_cmd_opt *popt = (Blaze_cmd_opt*) calloc (1, sizeof(Blaze_cmd_opt)); | |
964 | ||
965 | popt->logFileName = NULL; | |
966 | popt->configfile = (char*) strdup (DEFAULT_RC_FILE); | |
967 | popt->progname = (char*) strdup ("blaze"); | |
968 | popt->restore_dir = NULL; | |
969 | popt->cmdline_mode = 0; | |
970 | popt->tsync_port = TSYNC_PORT; | |
971 | popt->execfiles = new std::list<char *>(); | |
972 | popt->start_python = 0; | |
973 | gethostname(hostname, MAXHOSTNAMELEN); | |
974 | sprintf (ovd, "./overlayDir.%d.%s", getpid(), hostname); | |
975 | popt->overlaydir = (char*)strdup (ovd); | |
976 | ||
977 | SYSTEM_set_goodtrap_pc(0x0); | |
978 | SYSTEM_set_badtrap_pc(0x0); | |
979 | ||
980 | /* Figure out the name of this program. */ | |
981 | ||
982 | if (argc < 1) { | |
983 | popt->progname = strdup("blaze"); | |
984 | } else if ( (popt->progname = strrchr(argv[0], '/')) ) { | |
985 | ++popt->progname; | |
986 | } else { | |
987 | popt->progname = argv[0]; | |
988 | } | |
989 | ||
990 | int argndx = 1; | |
991 | while(argndx < argc) { | |
992 | const char *nextarg = argv[argndx++]; | |
993 | ||
994 | // | |
995 | // Try(!) to keep these alphabetically ordered... | |
996 | // | |
997 | ||
998 | if (StrEq(nextarg, "-badtrap")) { // Bad trap | |
999 | char * arg = argv[argndx++]; | |
1000 | char * end; // dummy | |
1001 | if (argndx > argc) { | |
1002 | ui->error("no argument specified to -goodtrap\n"); | |
1003 | exit(4); | |
1004 | } | |
1005 | SYSTEM_set_badtrap_pc(strtoull(arg, &end, 0)); | |
1006 | ||
1007 | } else if (StrEq(nextarg, "-c")) { // the RC file | |
1008 | if (argndx >= argc) { | |
1009 | ui->error("Missing arg for -c option\n "); | |
1010 | exit(1); | |
1011 | } | |
1012 | popt->configfile = strdup(argv[argndx++]); | |
1013 | if ( ! isFile(popt->configfile) ) { | |
1014 | ||
1015 | ui->error("Unable to open config file (%s).\n", | |
1016 | popt->configfile); | |
1017 | exit(2); | |
1018 | } | |
1019 | ||
1020 | } else if (StrEq(nextarg, "-f")){ | |
1021 | if (argndx >= argc) { | |
1022 | ui->error("Missing filename for -f option\n "); | |
1023 | exit(1); | |
1024 | } | |
1025 | // get the filename | |
1026 | popt->execfiles->push_back(strdup(argv[argndx++])); | |
1027 | ||
1028 | } else if (StrEq(nextarg, "-goodtrap")) { // Good trap | |
1029 | char * arg = argv[argndx++]; | |
1030 | char * end; // dummy | |
1031 | if (argndx > argc) { | |
1032 | ui->error("no argument specified to -goodtrap\n"); | |
1033 | exit(4); | |
1034 | } | |
1035 | SYSTEM_set_goodtrap_pc(strtoull(arg, &end, 0)); | |
1036 | ||
1037 | } else if (StrEq(nextarg, "-l")) { // log file | |
1038 | char * arg; | |
1039 | if (argndx >= argc) { | |
1040 | ui->error("Missing filename for -l option\n "); | |
1041 | exit(1); | |
1042 | } | |
1043 | popt->logFileName = strdup(argv[argndx++]); | |
1044 | ||
1045 | } else if (StrEq(nextarg, "-h")) { // help | |
1046 | usage(); | |
1047 | exit(1); | |
1048 | ||
1049 | } else if (StrEq(nextarg, "-nomemreserve")) { | |
1050 | ||
1051 | SYSTEM_set_memreserve (FALSE); | |
1052 | ||
1053 | } else if (StrEq(nextarg, "-obp")) { // obp boot option | |
1054 | obp_boot_option = TRUE; | |
1055 | ||
1056 | } else if (StrEq(nextarg, "-R")) { // Restore from dump | |
1057 | DIR *rdir; | |
1058 | if (argndx >= argc) { | |
1059 | ui->error("Wrong usage of -R option\n "); | |
1060 | exit(1); | |
1061 | } | |
1062 | rdir = opendir (argv[argndx]); | |
1063 | if (rdir == NULL) { | |
1064 | ui->error("<%s> restore directory is not found", argv[argndx]); | |
1065 | exit(1); | |
1066 | } | |
1067 | popt->restore_dir = (char*)strdup(argv[argndx++]); | |
1068 | popt->cmdline_mode |= CMM_RESTORE; | |
1069 | closedir(rdir); | |
1070 | ||
1071 | } else if (StrEq(nextarg, "-v") || StrEq(nextarg,"-version")) { // Version | |
1072 | /* see also version_ui_cmd() */ | |
1073 | ui->output("SAM VERSION %s\n", BLAZEVERSION_STRING); | |
1074 | ui->output("BUILT ON %s, AT %s, IN %s\n", __DATE__,__TIME__,__CWD__); | |
1075 | /*if (StrEq(nextarg,"-version"))*/ | |
1076 | exit(0); | |
1077 | ||
1078 | } else if (StrEq(nextarg, "-w")) { // pop-up window for console | |
1079 | // | |
1080 | // if there is a next argument and it does not start with a '-', | |
1081 | // it must be the display specification | |
1082 | char *arg; | |
1083 | popt->console_display_name = NULL; | |
1084 | if (argndx < argc) { | |
1085 | arg = argv[argndx++]; | |
1086 | if ((arg[0] != 0) && (arg[0] != '-')) { | |
1087 | popt->console_display_name = strdup(arg); | |
1088 | } | |
1089 | else { | |
1090 | argndx--; | |
1091 | } | |
1092 | } | |
1093 | // try to get console display id from the $DISPLAY env var | |
1094 | arg = getenv("DISPLAY"); | |
1095 | if (arg != NULL) { | |
1096 | popt->console_display_name = strdup(arg); | |
1097 | } | |
1098 | if (popt->console_display_name != NULL) { | |
1099 | console_display = strdup(popt->console_display_name); | |
1100 | pop_window = true; | |
1101 | }else{ | |
1102 | ui->error("it seems that you forgot to set DISPLAY environment variable.\n"); | |
1103 | } | |
1104 | ||
1105 | } else if (StrEq(nextarg, "-y")) { // overlayDir | |
1106 | char *arg = argv[argndx++]; | |
1107 | popt->overlaydir = (char*) strdup(arg); | |
1108 | ||
1109 | } else if (StrEq(nextarg, "-py")) { // overlayDir | |
1110 | popt->start_python = 1; | |
1111 | ||
1112 | } else if (StrEq(nextarg, "--") || (nextarg[0] != '-')) { | |
1113 | ||
1114 | // Consume all remaining options on the commandline. | |
1115 | // These remaining options are passed on to the python | |
1116 | // interpreter when it is loaded | |
1117 | ||
1118 | if (nextarg[0] != '-') | |
1119 | --argndx; | |
1120 | ||
1121 | app_argv = (char**)calloc(argc - argndx,sizeof(char*)); | |
1122 | ||
1123 | for (; argndx < argc; argndx++) | |
1124 | app_argv[app_argc++] = argv[argndx]; | |
1125 | popt->start_python = 1; | |
1126 | ||
1127 | } else { // invalid option | |
1128 | ui->error("Invalid argument (%s). -h for help\n", nextarg); | |
1129 | exit(1); | |
1130 | } | |
1131 | } | |
1132 | ||
1133 | return popt; | |
1134 | ||
1135 | ||
1136 | }//handle_args | |
1137 | ||
1138 | //////////////////////////////////////////////////////////// | |
1139 | ||
1140 | static void print_banner() | |
1141 | { | |
1142 | #ifdef OLD_LL | |
1143 | ui->fatal("\nWELCOME TO SAM [old LL] : %s\n\n", version); | |
1144 | #else | |
1145 | ui->output("\nSAM Version %s, Copyright (c) 2001-2007 Sun Microsystems, Inc.\n\n", version); | |
1146 | #endif | |
1147 | } | |
1148 | ||
1149 | ||
1150 | ////////////////////////////////////////////// | |
1151 | // | |
1152 | // Wrappers for functions passed to thr_create() . | |
1153 | // BLAZE being compiled with IO_THREAD - TRUE | |
1154 | // creates separate thread for every supported disk | |
1155 | // as well as for SERIAL device and NETWORK ADAPTER. | |
1156 | // (IO_THREAD applies to DISK only) | |
1157 | // | |
1158 | // | |
1159 | void * | |
1160 | term_thread_wrapper(void * arg) | |
1161 | { | |
1162 | term_thread(arg); | |
1163 | return (void *) 0x0; | |
1164 | } | |
1165 | ||
1166 | ||
1167 | ||
1168 | /* | |
1169 | * ******* the signal() system-call's effect is NOT persistent ******* | |
1170 | * the OS resets the signal's disposition to SIG_DFL before delivery, | |
1171 | * and the application MUST set it back. | |
1172 | */ | |
1173 | ||
1174 | ||
1175 | ||
1176 | void | |
1177 | sigignore_handler (int sig) | |
1178 | { | |
1179 | signal (sig, sigignore_handler); /* !!! MUST !!! */ | |
1180 | } | |
1181 | ||
1182 | ||
1183 | void | |
1184 | sigconfirm_handler (int sig) | |
1185 | { | |
1186 | char response [1000]; | |
1187 | ||
1188 | switch (sig) { | |
1189 | ||
1190 | case SIGHUP: // wait-a-minute, user can't see anything after a hang-up.?.!!. | |
1191 | ui->output("HANGUP received, type \"yes\" to terminate SAM:"); | |
1192 | gets (response); | |
1193 | if (strcmp (response, "yes") == 0) | |
1194 | exit (1); | |
1195 | break; | |
1196 | ||
1197 | case SIGINT: | |
1198 | ui->output("BREAK received, type \"yes\" to terminate SAM:"); | |
1199 | gets (response); | |
1200 | if (strcmp (response, "yes") == 0) | |
1201 | exit (1); | |
1202 | break; | |
1203 | ||
1204 | case SIGQUIT: | |
1205 | ui->output("CTRL-C received, type \"yes\" to terminate SAM:"); | |
1206 | gets (response); | |
1207 | if (strcmp (response, "yes") == 0) | |
1208 | exit (1); | |
1209 | break; | |
1210 | } | |
1211 | ||
1212 | signal (sig, sigconfirm_handler); /* !!! MUST !!! */ | |
1213 | } | |
1214 | ||
1215 | ||
1216 | ||
1217 | ||
1218 | /* since we don't resume from these signals we dont have to restore them */ | |
1219 | ||
1220 | void | |
1221 | sigtermination_handler (int /* sig */) | |
1222 | { | |
1223 | ui->output("main/sigterm_handler calling exit...\n"); | |
1224 | exit(1); /* execute cleanup functions registered by atexit()*/ | |
1225 | } | |
1226 | ||
1227 | void | |
1228 | sigcore_handler(int sig, siginfo_t *si, void *arg2) | |
1229 | { | |
1230 | uint64_t pc, npc; | |
1231 | ||
1232 | struct ucontext *up = (struct ucontext *) arg2; | |
1233 | ||
1234 | ui->output("\n\n"); | |
1235 | ui->output("**********************************************\n"); | |
1236 | ui->output("***** SAM received fatal signal, exiting *****\n"); | |
1237 | ui->output("**********************************************\n"); | |
1238 | ui->output("\n"); | |
1239 | ||
1240 | ui->output("signal %d occurred. \n", sig); | |
1241 | ui->output("siginfo: signo 0x%x \n", si->si_signo); | |
1242 | ui->output("siginfo: errno 0x%x \n", si->si_errno); | |
1243 | ui->output("siginfo: code 0x%x \n", si->si_code); | |
1244 | ||
1245 | ||
1246 | // how's this supposed to help, in an M-P simulator ?!. | |
1247 | ||
1248 | pc = (uint64_t) up->uc_mcontext.gregs[1]; | |
1249 | npc = (uint64_t) up->uc_mcontext.gregs[2]; | |
1250 | ||
1251 | ui->output("signal occurred at pc ---> 0x%llx %lld \n", pc, pc); | |
1252 | ui->output("signal occurred at npc ---> 0x%llx %lld \n", npc, npc); | |
1253 | ui->output("\n\n"); | |
1254 | ||
1255 | exit(1); | |
1256 | } | |
1257 | ||
1258 | ||
1259 | ||
1260 | ||
1261 | ||
1262 | // ============================================================================ | |
1263 | // | |
1264 | // HOSTINFO_ stuff... | |
1265 | // | |
1266 | ||
1267 | int HOSTINFO_numcpus() | |
1268 | { | |
1269 | static int numcpus = 0; | |
1270 | ||
1271 | if (!numcpus) { | |
1272 | // @@@ there's got to be a better way...???... | |
1273 | // @@@ this is so inefficient that we can't be re-doing this each | |
1274 | // @@@ time we're called... | |
1275 | // @@@ but that's what system-worker-threads really need... | |
1276 | FILE * FL = popen ("/usr/sbin/psrinfo | /bin/grep on-line | /bin/wc", "r"); | |
1277 | char buf[100]; | |
1278 | fgets (buf, 100, FL); | |
1279 | if (sscanf (buf, "%i", &numcpus) == NULL) { | |
1280 | ui->error("***HINFO: can nott get numcpus\n"); | |
1281 | } | |
1282 | } | |
1283 | return numcpus; | |
1284 | } | |
1285 | ||
1286 | ||
1287 | ||
1288 | // =============================================================================== | |
1289 | // | |
1290 | // Clean up overlaydir during exit, register only once when overlaydir is created | |
1291 | // | |
1292 | // =============================================================================== | |
1293 | void | |
1294 | overlaydir_cleanup() | |
1295 | { | |
1296 | if (isDir(overlaydir)) { | |
1297 | char *rmrf = (char*) malloc (strlen(overlaydir) + 32); | |
1298 | sprintf (rmrf, "rm -rf %s ", overlaydir); | |
1299 | int status = system (rmrf); | |
1300 | ||
1301 | if (status != 0) { | |
1302 | const char* perr = strerror(errno); | |
1303 | ui->output("overlay dir cleanup: rmdir(%s) => %d (%s)\n", overlaydir, status, perr); | |
1304 | } | |
1305 | ||
1306 | free(rmrf); | |
1307 | } | |
1308 | } |