Initial commit of OpenSPARC T2 architecture model.
[OpenSPARC-T2-SAM] / sam-t2 / sam / system / blaze / main.cc
CommitLineData
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
85typedef 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"
105int scsi_ctrl_count = 0;
106devRegistry * samDevs;
107uint64_t property_list::fkprom_dtinbuf_pa = 0x50;
108int property_list::fkprom_dtinbuf_offset = 0x0;
109
110vtracer_async_queue * trace_async_queue = NULL;
111
112
113///////////////////////////////////////////////
114int blaze_debug = 0;
115int blaze_option = 0;
116///////////////////////////////////////////////
117
118char version[] = BLAZEVERSION_STRING; // version.h
119//configstate_t *config_arch = NULL;
120
121
122/* */
123volatile e_blaze_runstate_t blaze_run_state = e_BLAZE_INVALID;
124volatile int blaze_stop_request = 0;
125
126
127static int openasroot = 0; // open disk devs as root?
128
129int obp_boot_option = 0; // default to fakeprom
130
131
132/* Memory Object */
133memT *mm1 = NULL;
134
135
136
137 // this is the master clock // not a clock, is total of all cpus !
138volatile uint64_t global_tick = 0; // should be in system.cc, be static
139
140/* For terminal output to a file */
141
142typedef 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
163Blaze_cmd_opt *Popt = NULL;
164const char * overlaydir = NULL;
165
166
167
168archglobals_t volatile the_arch = { 0 };
169archglobals_t the_arch_backup = { 0 };
170
171volatile int64_t the_arch_cmips = 0; /* sw05b Hack */
172volatile int the_arch_ccntx = 0;
173
174
175
176extern "C" {
177void sigcore_handler(int sig, siginfo_t *si, void *arg2);
178
179void sigignore_handler(int sig);
180void sigconfirm_handler(int sig);
181void sigtermination_handler(int sig);
182}
183
184static void init_devices();
185
186static void copy_configuration(const archglobals_t& arch_src,
187 archglobals_t *arch_dest);
188static void verify_configuration(const archglobals_t& arch_src,
189 const archglobals_t& arch_dest);
190
191static void init_config_arch ();
192
193// FORWARD DECLARATIONS:
194bool_t vcpu_save(DR_OPAQUE pdr);
195bool_t vcpu_restore(DR_OPAQUE pdr);
196
197
198/* Externals */
199extern void start_filecmd_check (SimCmd* state);
200int check_tick_cmpr;
201extern VCPU_ExInterface g_cpu_ex_intf;
202extern char cpu_lib_name[160];
203
204/*
205 * Major Paine Threads
206 */
207void sim_thread_loop (SimCmd*);
208
209#ifdef __cplusplus
210extern "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
222static int app_argc = 0;
223static char** app_argv = 0;
224
225/*
226 * Handle Command Line Options
227 * For getopt() library routine
228 */
229
230extern char *optarg;
231extern char ver[128];
232extern char second_ver[128];
233extern int optind;
234extern void* asi_ptr[];
235
236Blaze_cmd_opt* handle_args(int argc, char **argv);
237static void print_banner();
238
239const char* diskspecfile = "pcidisk.init";
240static SimCmd command;
241static int not_root_warning = 0;
242
243char *pty_dev_a, *pty_dev_b;
244char *pty_dev_c, *pty_dev_d;
245
246char* console_display;
247bool pop_window = false;
248
249
250extern uint64_t get_page_mask(int);
251
252
253
254
255////////////////////////////////////////////////////////////
256
257uint32_t BLAZE_restore_from_checkpoint ()
258{
259 return Popt->cmdline_mode & CMM_RESTORE;
260}
261
262void 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
310char *get_script_file()
311{
312 return Popt->configfile;
313}
314
315char *get_restore_dir()
316{
317 return Popt->restore_dir;
318}
319
320////////////////////////////////////////////////////////////
321
322serialInterface * systemConsole; // system console pointer
323
324int 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////////////////////////////////////////////////////////
368int 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////////////////////////////////////////////////////////
383int 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//
414Vcpu * 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//
475bool_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//
485bool_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//
497void 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
510extern int term_console (char *pty_dev, char *display);
511
512#ifdef BS_WRAPPER
513#ifdef __cplusplus
514extern "C" {
515#endif
516extern 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 */
536void 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
571static 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
615static bool sysconf_done = false;
616
617bool SYSTEM_sysconf_done() { return sysconf_done; }
618
619// called after last sysconf line in RC file has been parsed.
620
621static 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
635static 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
683static 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
728extern void ui_readline();
729
730int 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
845void 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
862static 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//
886static void
887copy_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//
901static void
902verify_configuration(const archglobals_t& /* arch_src */,
903 const archglobals_t& /* arch_dest */)
904{
905}
906
907
908void 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
935static int
936StrEq(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
957Blaze_cmd_opt *
958handle_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
1140static 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//
1159void *
1160term_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
1176void
1177sigignore_handler (int sig)
1178{
1179 signal (sig, sigignore_handler); /* !!! MUST !!! */
1180}
1181
1182
1183void
1184sigconfirm_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
1220void
1221sigtermination_handler (int /* sig */)
1222{
1223 ui->output("main/sigterm_handler calling exit...\n");
1224 exit(1); /* execute cleanup functions registered by atexit()*/
1225}
1226
1227void
1228sigcore_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
1267int 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// ===============================================================================
1293void
1294overlaydir_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}