// ========== Copyright Header Begin ==========================================
// OpenSPARC T2 Processor File: main.cc
// Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved.
// DO NOT ALTER OR REMOVE COPYRIGHT NOTICES.
// The above named program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public
// License version 2 as published by the Free Software Foundation.
// The above named program is distributed in the hope that it will be
// useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// General Public License for more details.
// You should have received a copy of the GNU General Public
// License along with this work; if not, write to the Free Software
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
// ========== Copyright Header End ============================================
* Copyright (C) 1996, 2001 Sun Microsystems, Inc.
#pragma ident "@(#)1.36 03/06/02 main.cc"
* Copyright (c) 1989, Sun Microsystems, Inc. All Rights Reserved. Sun
* considers its source code as an unpublished, proprietary trade secret, and
* it is available only under strict license provisions. This copyright
* notice is placed here only to protect Sun in the event the source is
* deemed a published work. Disassembly, decompilation, or other means of
* reducing the object code to human readable form is prohibited by the
* license agreement under which this code is provided to the user or company
* in possession of this copy
* RESTRICTED RIGHTS LEGEND: Use, duplication, or disclosure by the
* Government is subject to restrictions as set forth in subparagraph
* (c) (1) (ii) of the Rights in Technical Data and Computer Software clause
* at DFARS 52.227-7013 and in similar clauses in the FAR and NASA FAR
/* standard C includes */
#include "blaze_globals.h"
#include "sim_cmd_struct.h"
typedef void* TM_OPAQUE_DATA
;
#include "vtracer_async_queue.h"
// to access serial device
#include "dev_registry.h"
#define DEFAULT_RC_FILE ".blazerc"
uint64_t property_list::fkprom_dtinbuf_pa
= 0x50;
int property_list::fkprom_dtinbuf_offset
= 0x0;
vtracer_async_queue
* trace_async_queue
= NULL
;
///////////////////////////////////////////////
///////////////////////////////////////////////
char version
[] = BLAZEVERSION_STRING
; // version.h
//configstate_t *config_arch = NULL;
volatile e_blaze_runstate_t blaze_run_state
= e_BLAZE_INVALID
;
volatile int blaze_stop_request
= 0;
static int openasroot
= 0; // open disk devs as root?
int obp_boot_option
= 0; // default to fakeprom
// this is the master clock // not a clock, is total of all cpus !
volatile uint64_t global_tick
= 0; // should be in system.cc, be static
/* For terminal output to a file */
std::list
<char *> *execfiles
;
char *console_display_name
;
FILE *serial_output_file
;
char *serial_output_fname
;
Blaze_cmd_opt
*Popt
= NULL
;
const char * overlaydir
= NULL
;
archglobals_t
volatile the_arch
= { 0 };
archglobals_t the_arch_backup
= { 0 };
volatile int64_t the_arch_cmips
= 0; /* sw05b Hack */
volatile int the_arch_ccntx
= 0;
void sigcore_handler(int sig
, siginfo_t
*si
, void *arg2
);
void sigignore_handler(int sig
);
void sigconfirm_handler(int sig
);
void sigtermination_handler(int sig
);
static void init_devices();
static void copy_configuration(const archglobals_t
& arch_src
,
archglobals_t
*arch_dest
);
static void verify_configuration(const archglobals_t
& arch_src
,
const archglobals_t
& arch_dest
);
static void init_config_arch ();
bool_t
vcpu_save(DR_OPAQUE pdr
);
bool_t
vcpu_restore(DR_OPAQUE pdr
);
extern void start_filecmd_check (SimCmd
* state
);
extern VCPU_ExInterface g_cpu_ex_intf
;
extern char cpu_lib_name
[160];
void sim_thread_loop (SimCmd
*);
void * term_thread_wrapper(void *); // simulated system console
// The -- option (or first non option) stops the blaze commandline
// parsing and all remaining options are put into the app_argv
// vector. These remaining options are passed on to the
// python interpreter when it is loaded
static char** app_argv
= 0;
* Handle Command Line Options
* For getopt() library routine
extern char second_ver
[128];
Blaze_cmd_opt
* handle_args(int argc
, char **argv
);
static void print_banner();
const char* diskspecfile
= "pcidisk.init";
static int not_root_warning
= 0;
char *pty_dev_a
, *pty_dev_b
;
char *pty_dev_c
, *pty_dev_d
;
extern uint64_t get_page_mask(int);
////////////////////////////////////////////////////////////
uint32_t BLAZE_restore_from_checkpoint ()
return Popt
->cmdline_mode
& CMM_RESTORE
;
int v
, sv
, ssv
= 0; FILE *fp
; char rfile
[PATH_MAX
];
sprintf (rfile
, SAM_VERSION_FILE
, get_restore_dir());
sprintf (rfile
, BLAZE_VERSION_FILE
, get_restore_dir());
ui
->warning("No SAM version is specified in the dump\n ");
ui
->warning("there is no guarantee of successfull restoration!!\n ");
if (fgets (ver
, 120, fp
) == NULL
)
ui
->warning("CHECKPOINT might be corrupted!!\n ");
ui
->output("CHECKPOINT of SAM v %s\n ", ver
);
sprintf (rfile
, SECONDARY_VERSION_FILE
, get_restore_dir());
if (fgets (second_ver
, 120, fp
) == NULL
)
ui
->warning("Secondary V4 dump info lost!\n ");
ui
->output("Secondary V4 version: %s\n ", second_ver
);
if (strcmp(DEFAULT_RC_FILE
, Popt
->configfile
))
return; // specified by '-c' already
sscanf(ver
, "%d.%d.%d", &v
, &sv
, &ssv
);
if (v
> 5 || v
== 5 && sv
>= 5) {
sprintf(rfile
, "%s/%s", get_restore_dir(), RC_DUMP
);
if (isFile((const char *)rfile
))
Popt
->configfile
= (char*)strdup(rfile
);
if (!isFile(Popt
->configfile
)) {
ui
->error("No script file for restoring!\n");
return Popt
->restore_dir
;
////////////////////////////////////////////////////////////
serialInterface
* systemConsole
; // system console pointer
uint8_t *c
, // character to read/write
int wr
// 0 - read, 1 - write
ui
->error("systemConsole pointer null. Possible configuration problem!!\n");
/* Write the intent of READING the register 0x0 */
systemConsole
->reg_access( (char *)&buf
, PORT_A_CONTROL
, 0x1);
/* Read the register that the SERIAL CONTROL REGISTER is pointing to */
systemConsole
->reg_access( (char *)&buf
, PORT_A_CONTROL
, 0x0);
/* If data is available */
if (buf
& RX_CHAR_AVAILABLE
)
/* Read the port register */
systemConsole
->reg_access((char *)&buf
, PORT_A_DATA
, 0x0);
else // no data available
*c
= uint8_t(buf
); // char read
systemConsole
->reg_access((char *)&buf
, PORT_A_DATA
, 0x1);
////////////////////////////////////////////////////////
int wr
, // operation code
uint64_t paddr
, // physical address
uint32_t size
, // access size
uint64_t &data
, // 64 bit value to read/write
uint64_t bitmask
// access bit mask
return SYSTEM_physio_access ( cpuid
, NULL
, paddr
, bool_t(wr
), size
, &data
, uint8_t(bitmask
) );
////////////////////////////////////////////////////////
int operation
, // operation code
uint32_t asi
, // asi value
uint64_t vaddr
, // virtual address
int32_t size
, // access size
uint64_t &buf
// 64 bit data value
// loadable modules that implement external asi should be
if ((operation
== VCPU_LOAD_OP
)) {
rc
= TM_execute_load_asi (asi
, vaddr
, &buf
, size
, sid
);
else { // operation == store
rc
= TM_execute_store_asi (asi
, vaddr
, &buf
, size
, sid
);
///////////////////////////////////
Vcpu
* init_cpu ( char *path
, int argc
, char **argv
)
VCPU_Config config_info
; // cpu config params
set_default ( config_info
);
// parse configuration parameters
for ( int i
=0; i
<argc
; i
++)
if ( set_param ( argv
[i
], &config_info
) != 0)
ui
->error("cannot set cpu param %s\n", argv
[i
]);
// system interface for the cpu module
sys_intf
.access_io
= access_io_cb
;
sys_intf
.access_serial
= access_serial_cb
;
sys_intf
.access_asi
= access_asi_cb
;
sys_intf
.vtrace
= NULL
; //instruction_cb;
sys_intf
.mem
= mm1
; // sys mem
Vcpu
* vcpu
= create_cpu ( path
, config_info
, &sys_intf
);
ui
->error( "FATAL : unable to create CPU %d \n",
// for compatibility with v4 dump/restore skip "blaze" cpu model
if ((id
== 0) && ((vcpu
->config
.cpu_type
& VCPU_IMPL_SIM_MASK
) != VCPU_IMPL_SIM_BLAZE
))
DR_register( (char*)"cpu", vcpu_save
, vcpu_restore
, vcpu
);
if (trace_async_queue
== NULL
) {
trace_async_queue
= new vtracer_async_queue
;
//////////////////////////////////////////////////
// save a vcpu (for dump/restore)
bool_t
vcpu_save(DR_OPAQUE pdr
)
char *dir
= DR_get_dir();
return g_cpu_ex_intf
.save(dir
);
//////////////////////////////////////////////////
// restore a vcpu (for dump/restore)
bool_t
vcpu_restore(DR_OPAQUE pdr
)
char *dir
= DR_get_rdir (pdr
);
return g_cpu_ex_intf
.restore(dir
);
//////////////////////////////////////////////////
// Creates TERMINAL/CONSOLE Thread
thread_t termThread
; // special thread that handles terminal IO
thr_create(NULL
, NULL
, term_thread_wrapper
, NULL
,
THR_BOUND
|THR_DAEMON
, &termThread
);
//////////////////////////////////////////////////
extern int term_console (char *pty_dev
, char *display
);
extern void init_simix();
/* ------------------------------------------------------------------------
* whats weird about unix/posix/solaris signal handlers is that they are
* process-wide, you cannot have a different handler for each thread,
* so we register all signal handlers here...
* (you can block/unblock signals on a per-thread basis, which we do,
* and which is done inside each thread separately as necessary).
void init_signal_handlers ()
/***** core dump signals **************** SIGBUS, SIGSEGV, SIGILL ******/
sact
.sa_sigaction
= sigcore_handler
;
sact
.sa_flags
= SA_SIGINFO
| SA_RESETHAND
;
sigaction(SIGBUS
, &sact
, NULL
);
sigaction(SIGSEGV
, &sact
, NULL
);
sigaction(SIGILL
, &sact
, NULL
);
/***** must ignore signals ********************* SIGPIPE, SIGUSR1 ******/
// must ignore sigpipe or blaze will crash whenever switchsim does
signal (SIGPIPE
, sigignore_handler
);
// for unsticking blaze threads that are stuck in blocking IO
// for terminating workerthreads so we can reconfigure
signal (SIGUSR1
, sigignore_handler
); /* disconnect (and park) rcvr-thread */
signal (SIGINT
, sigignore_handler
); /* kill worker-thread */
/***** special case signals ********************* SIGINT, SIGQUIT ******/
/* signal handler for blaze-keyboard -> ask for user confirmation */
// be user friendly, don't let accidental ctrl-C kill blaze !!!
signal (SIGINT
, sigconfirm_handler
); /* BREAK */
signal (SIGQUIT
, sigconfirm_handler
); /* CTRL-C */
/*signal (SIGHUP, sigconfirm_handler); * HangUp */
// we're still not sure what this means or what to do when it happens...
// /* signal handler for blaze-nonmaskable-termination -> ? */
// // graceful shutdown before nonmaskable kill signal ???
signal (SIGTERM
, sigtermination_handler
);
} // -----------------------------------------------------------------------
// Search for $SAM/etc/<proc>_samrc and add it to the Popt->execfiles list
static void samrc_init() {
const char *cpu_name
= vcpu
->cpu_name(vcpu
->config
.cpu_type
);
const char* exec_name
= getexecname();
(sam_dir
= strdup(exec_name
)) == NULL
||
(sam_dir
= dirname(sam_dir
)) == NULL
) {
ui
->error("can't allocate memory while searching for "
"$SAM/bin/sam\n", cpu_name
);
// Here sam_dir should point to $SAM/bin; check to make sure.
int sam_dir_len
= strlen(sam_dir
);
if (strcmp(&sam_dir
[sam_dir_len
- 4], "/bin") != 0) {
ui
->error("Non-standard sam installation; aborting "
"search for $SAM/etc/%s_samrc\n", cpu_name
);
sam_dir
[sam_dir_len
- 4] = '\0'; // Make sam-dir -> $SAM
// Allocate space for "$SAM/etc/<proc>_samrc" and use sprintf
(char *)malloc(sam_dir_len
+ sizeof("/etc/_samrc") +
if (samrc_name
== NULL
) {
ui
->error("can't allocate memory while searching for "
"$SAM/etc/%s_samrc\n", cpu_name
);
sprintf(samrc_name
, "%s/etc/%s_samrc", sam_dir
, cpu_name
);
// If the <proc>_samrc file exists, prepend it to the list of files
// to execute at start up.
if (stat(samrc_name
, &stat_buf
) != -1)
Popt
->execfiles
->push_front(samrc_name
);
static bool sysconf_done
= false;
bool SYSTEM_sysconf_done() { return sysconf_done
; }
// called after last sysconf line in RC file has been parsed.
static void complete_initialization()
TM_module_init(); // report MMI_CONFIG_INIT_DONE
if (BLAZE_restore_from_checkpoint()) {
restore_devices_action(get_restore_dir());
ui
->output("----- RESTORE COMPLETED -----\n");
static void process_rc_file(const char * fn
){
FILE * fp
= fopen(fn
,"r");
ui
->error("Can not open SAM RC file %s\n",fn
);
const int max_buf_size
= 1024 * 10;
// find the line number of last uncommented sysconf in RC file
// this assumes that all conf's, loads are before last sysconf.
// XXX : to be removed if -f <filename> becomes the norm
int line
= 0; int cntr
= 0;
while(fgets(buf
,max_buf_size
,fp
)){
while(buf
[buf_index
] && isspace(buf
[buf_index
]))
if(buf
[buf_index
] == '#')
continue; // skip comment line
if(!strncmp("sysconf",buf
+ buf_index
,strlen("sysconf")) \
&& isspace( *(buf
+buf_index
+ strlen("sysconf")) ))
while(fgets(buf
,max_buf_size
,fp
)){
complete_initialization();
// -f <filename> SAM command line option
static void process_command_file(const char * fn
){
FILE * fp
= fopen(fn
,"r");
ui
->error("Can not open SAM command file %s\n",fn
);
const int max_buf_size
= 1024 * 10;
// make sure that there are no sysconf's in the command file
// make sure that there are no conf's in the command file
int sysconf_line
= -1; int conf_line
= -1; int cntr
= 0;
while(fgets(buf
,max_buf_size
,fp
)){
while(buf
[buf_index
] && isspace(buf
[buf_index
]))
if(buf
[buf_index
] == '#')
continue; // comment line
if(!strncmp("sysconf",buf
+ buf_index
,strlen("sysconf")) \
&& isspace( *(buf
+buf_index
+ strlen("sysconf")) )){
if(!strncmp("conf",buf
+ buf_index
,strlen("conf")) \
&& isspace( *(buf
+buf_index
+ strlen("conf")) )){
ui
->error("command file %s has sysconf directive\n",fn
);
while(fgets(buf
,max_buf_size
,fp
)){
extern void ui_readline();
int main (int argc
, char **argv
)
init_SYSTEM_open (); // sets up search path for "load" ui cmds
for (int i
=0; i
<MAX_MP
; i
++) cpu_enabled
[i
] = 1;
// Rummage up some additional file descriptors
getrlimit(RLIMIT_NOFILE
, &rl
);
rl
.rlim_cur
= rl
.rlim_max
;
setrlimit(RLIMIT_NOFILE
, &rl
);
// get command line arguments
Popt
= handle_args (argc
,argv
);
// to setup some necessary default values in THE_ARCH
char *rdt_name
= term_redirect_get_file ();
ui
->output("console input redirected from <%s> \n", rdt_name
);
// logging/debugging initialization
if ((logfile
= fopen(Popt
->logFileName
, "w+")) == NULL
) {
ui
->error("Unable to open log file <%s>", Popt
->logFileName
);
ui
->set_log_file(logfile
);
// Get dump version for the requirement of some constructors of device modules.
if (BLAZE_restore_from_checkpoint())
// to prepare for UI command registering
// init loadable module support
// dump/restore initialization, before UI thread initiated.
init_threads(); // includes all CPU related threads start
samDevs
= new devRegistry();
// process the configeRC file before starting the UI thread
process_rc_file(Popt
->configfile
);
init_ui (Popt
->configfile
, TRUE
);
// Load python if user specified -py
std::string cmd
= "run-python-file";
for (int i
=0; i
< app_argc
; i
++)
// no python application specified, load dummy
UI_exec_cmd((char*)cmd
.c_str());
// check to see if there is -f <filename> option provided
// if yes, execute the UI commands in there
for (std::list
<char*>::iterator iter
= Popt
->execfiles
->begin();
iter
!= Popt
->execfiles
->end();
process_command_file(*iter
);
// Jump into the readline enabled ui handler. We exit
// there on quit (or eof).
// just wait for all child threads (CPU, I/O, net, UI) to complete
while (thr_join(0, NULL
, NULL
) == 0 ) {
;//sleep(1); ** no reason to sleep, thr_join will select a thrd **
ui
->fatal("unexpected termination!!! \n");
////////////////////////////////////////////////////////
int uid
= getuid(); // me
int euid
= geteuid(); // root
int status
= seteuid(uid
); // backdown from root
// do not do it again in pcidisk.cc
ui
->verbose("For all disks : overlay directory is <%s> \n", Popt
->overlaydir
);
overlaydir
= (char*)strdup(Popt
->overlaydir
);
//////////////////////////////////////////////////
static void init_config_arch () {
the_arch
.mmutype
= (char*)strdup("cheetahplus");
the_arch
.mmutype
= (char*)strdup("cheetah");
the_arch
.cpus_per_thread
= -1;
the_arch
.numthreads
= -1;
// make a copy of the original config.init values
copy_configuration(const archglobals_t
& arch_src
,
archglobals_t
*arch_dest
)
// first do a bit-by-bit copy
memcpy((void *)arch_dest
, (const void *)&arch_src
, sizeof(archglobals_t
));
// then do a real copy on string
arch_dest
->mmutype
= strdup(arch_src
.mmutype
);
// comapre the configuration values in config.init with the newly
// inputted values (from restore operation, e.g.)
verify_configuration(const archglobals_t
& /* arch_src */,
const archglobals_t
& /* arch_dest */)
-c CFILE - use configuration file CFILE (eg: -c sam.rc)\n\
-R path - restore from dump directory specified in <path>\n\
-goodtrap <pc> - (SAM-only) exit on this pc_va; return 0\n\
-badtrap <pc> - (SAM-only) exit on this pc_va; return 1\n\
-v(ersion) - print version and exit\n\
-w - start xterm window for sim console\n\
-y ovdir - put disk overlays in OVDIR (do not use /tmp for big files)\n\
-f <filename> - execute SAM UI commands in <filename> after RC file is processed\n\
-- <arg0> ... - start Pyhton if py does not occur in RC file, execute\n\
arg0 (if present) as script file passing other args as args to script file.\n\
If py specified in rc file, pass all arguments w/o interpretation to Python\n\
-l LFILE - use log file LFILE\n\
-obp - boot CH/CH+ SAM with COBP\n\
-nomemreserve - allocate simulated memory on demand. Only supported on builds with flat memory model. \n\
////////////////////////////////////////////////////
StrEq(const char *s1
, const char *s2
) {
if ( (s1
==NULL
) || (s2
==NULL
)) {
// Handle Command Line options
handle_args (int argc
, char **argv
)
char hostname
[MAXHOSTNAMELEN
];
char ovd
[MAXHOSTNAMELEN
+ 64];
Blaze_cmd_opt
*popt
= (Blaze_cmd_opt
*) calloc (1, sizeof(Blaze_cmd_opt
));
popt
->logFileName
= NULL
;
popt
->configfile
= (char*) strdup (DEFAULT_RC_FILE
);
popt
->progname
= (char*) strdup ("blaze");
popt
->restore_dir
= NULL
;
popt
->tsync_port
= TSYNC_PORT
;
popt
->execfiles
= new std::list
<char *>();
gethostname(hostname
, MAXHOSTNAMELEN
);
sprintf (ovd
, "./overlayDir.%d.%s", getpid(), hostname
);
popt
->overlaydir
= (char*)strdup (ovd
);
SYSTEM_set_goodtrap_pc(0x0);
SYSTEM_set_badtrap_pc(0x0);
/* Figure out the name of this program. */
popt
->progname
= strdup("blaze");
} else if ( (popt
->progname
= strrchr(argv
[0], '/')) ) {
popt
->progname
= argv
[0];
const char *nextarg
= argv
[argndx
++];
// Try(!) to keep these alphabetically ordered...
if (StrEq(nextarg
, "-badtrap")) { // Bad trap
char * arg
= argv
[argndx
++];
ui
->error("no argument specified to -goodtrap\n");
SYSTEM_set_badtrap_pc(strtoull(arg
, &end
, 0));
} else if (StrEq(nextarg
, "-c")) { // the RC file
ui
->error("Missing arg for -c option\n ");
popt
->configfile
= strdup(argv
[argndx
++]);
if ( ! isFile(popt
->configfile
) ) {
ui
->error("Unable to open config file (%s).\n",
} else if (StrEq(nextarg
, "-f")){
ui
->error("Missing filename for -f option\n ");
popt
->execfiles
->push_back(strdup(argv
[argndx
++]));
} else if (StrEq(nextarg
, "-goodtrap")) { // Good trap
char * arg
= argv
[argndx
++];
ui
->error("no argument specified to -goodtrap\n");
SYSTEM_set_goodtrap_pc(strtoull(arg
, &end
, 0));
} else if (StrEq(nextarg
, "-l")) { // log file
ui
->error("Missing filename for -l option\n ");
popt
->logFileName
= strdup(argv
[argndx
++]);
} else if (StrEq(nextarg
, "-h")) { // help
} else if (StrEq(nextarg
, "-nomemreserve")) {
SYSTEM_set_memreserve (FALSE
);
} else if (StrEq(nextarg
, "-obp")) { // obp boot option
} else if (StrEq(nextarg
, "-R")) { // Restore from dump
ui
->error("Wrong usage of -R option\n ");
rdir
= opendir (argv
[argndx
]);
ui
->error("<%s> restore directory is not found", argv
[argndx
]);
popt
->restore_dir
= (char*)strdup(argv
[argndx
++]);
popt
->cmdline_mode
|= CMM_RESTORE
;
} else if (StrEq(nextarg
, "-v") || StrEq(nextarg
,"-version")) { // Version
/* see also version_ui_cmd() */
ui
->output("SAM VERSION %s\n", BLAZEVERSION_STRING
);
ui
->output("BUILT ON %s, AT %s, IN %s\n", __DATE__
,__TIME__
,__CWD__
);
/*if (StrEq(nextarg,"-version"))*/
} else if (StrEq(nextarg
, "-w")) { // pop-up window for console
// if there is a next argument and it does not start with a '-',
// it must be the display specification
popt
->console_display_name
= NULL
;
if ((arg
[0] != 0) && (arg
[0] != '-')) {
popt
->console_display_name
= strdup(arg
);
// try to get console display id from the $DISPLAY env var
popt
->console_display_name
= strdup(arg
);
if (popt
->console_display_name
!= NULL
) {
console_display
= strdup(popt
->console_display_name
);
ui
->error("it seems that you forgot to set DISPLAY environment variable.\n");
} else if (StrEq(nextarg
, "-y")) { // overlayDir
char *arg
= argv
[argndx
++];
popt
->overlaydir
= (char*) strdup(arg
);
} else if (StrEq(nextarg
, "-py")) { // overlayDir
} else if (StrEq(nextarg
, "--") || (nextarg
[0] != '-')) {
// Consume all remaining options on the commandline.
// These remaining options are passed on to the python
// interpreter when it is loaded
app_argv
= (char**)calloc(argc
- argndx
,sizeof(char*));
for (; argndx
< argc
; argndx
++)
app_argv
[app_argc
++] = argv
[argndx
];
} else { // invalid option
ui
->error("Invalid argument (%s). -h for help\n", nextarg
);
////////////////////////////////////////////////////////////
static void print_banner()
ui
->fatal("\nWELCOME TO SAM [old LL] : %s\n\n", version
);
ui
->output("\nSAM Version %s, Copyright (c) 2001-2007 Sun Microsystems, Inc.\n\n", version
);
//////////////////////////////////////////////
// Wrappers for functions passed to thr_create() .
// BLAZE being compiled with IO_THREAD - TRUE
// creates separate thread for every supported disk
// as well as for SERIAL device and NETWORK ADAPTER.
// (IO_THREAD applies to DISK only)
term_thread_wrapper(void * arg
)
* ******* the signal() system-call's effect is NOT persistent *******
* the OS resets the signal's disposition to SIG_DFL before delivery,
* and the application MUST set it back.
sigignore_handler (int sig
)
signal (sig
, sigignore_handler
); /* !!! MUST !!! */
sigconfirm_handler (int sig
)
case SIGHUP
: // wait-a-minute, user can't see anything after a hang-up.?.!!.
ui
->output("HANGUP received, type \"yes\" to terminate SAM:");
if (strcmp (response
, "yes") == 0)
ui
->output("BREAK received, type \"yes\" to terminate SAM:");
if (strcmp (response
, "yes") == 0)
ui
->output("CTRL-C received, type \"yes\" to terminate SAM:");
if (strcmp (response
, "yes") == 0)
signal (sig
, sigconfirm_handler
); /* !!! MUST !!! */
/* since we don't resume from these signals we dont have to restore them */
sigtermination_handler (int /* sig */)
ui
->output("main/sigterm_handler calling exit...\n");
exit(1); /* execute cleanup functions registered by atexit()*/
sigcore_handler(int sig
, siginfo_t
*si
, void *arg2
)
struct ucontext
*up
= (struct ucontext
*) arg2
;
ui
->output("**********************************************\n");
ui
->output("***** SAM received fatal signal, exiting *****\n");
ui
->output("**********************************************\n");
ui
->output("signal %d occurred. \n", sig
);
ui
->output("siginfo: signo 0x%x \n", si
->si_signo
);
ui
->output("siginfo: errno 0x%x \n", si
->si_errno
);
ui
->output("siginfo: code 0x%x \n", si
->si_code
);
// how's this supposed to help, in an M-P simulator ?!.
pc
= (uint64_t) up
->uc_mcontext
.gregs
[1];
npc
= (uint64_t) up
->uc_mcontext
.gregs
[2];
ui
->output("signal occurred at pc ---> 0x%llx %lld \n", pc
, pc
);
ui
->output("signal occurred at npc ---> 0x%llx %lld \n", npc
, npc
);
// ============================================================================
// @@@ there's got to be a better way...???...
// @@@ this is so inefficient that we can't be re-doing this each
// @@@ time we're called...
// @@@ but that's what system-worker-threads really need...
FILE * FL
= popen ("/usr/sbin/psrinfo | /bin/grep on-line | /bin/wc", "r");
if (sscanf (buf
, "%i", &numcpus
) == NULL
) {
ui
->error("***HINFO: can nott get numcpus\n");
// ===============================================================================
// Clean up overlaydir during exit, register only once when overlaydir is created
// ===============================================================================
char *rmrf
= (char*) malloc (strlen(overlaydir
) + 32);
sprintf (rmrf
, "rm -rf %s ", overlaydir
);
int status
= system (rmrf
);
const char* perr
= strerror(errno
);
ui
->output("overlay dir cleanup: rmdir(%s) => %d (%s)\n", overlaydir
, status
, perr
);