// ========== Copyright Header Begin ==========================================
// OpenSPARC T2 Processor File: system.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) 2001, 2005 Sun Microsystems, Inc.
* UICMDS (ie functions called by ui)
* SYSCONF (legacy api, to be replace with real sysconf api soon...)
/* standard C includes */
#include "blaze_globals.h"
#include "workerthread.h"
uint32_t boot_ctrl_id
= 0;
uint32_t boot_target_id
= 0;
uint32_t boot_part_id
= 0;
uint32_t boot_disk_id
= 0;
extern void term_console_destroy (); // defined in term.cc
// ========================== GLOBAL VARIABLES ================================
// BS flags. Majority of them are needed only within startp time
static bool_t ce_enable_flag
= FALSE
;
static bool_t scsi_disk_enable_flag
= FALSE
;
static bool_t scsi_boot_enable_flag
= FALSE
;
static bool_t fc_disk_enable_flag
= FALSE
;
static bool_t fc_boot_enable_flag
= FALSE
;
static bool_t mem_reserve_flag
= TRUE
;
SystemT
*psys
= &the_sys
;
// The SAM UI is multi threaded; input can come from the user,
// the global time sync or a remote debugger for example. Every
// ui command needs to be executed whilst holding the lock. The
// ui_lock_held booleans is added to help in asserting this.
// The ui_cond variable is for synchronizing stop, see SYSTEM_wait_stop()
static bool ui_lock_held
;
// ============================================================================
// SYSTEM_open (like tracemod/mod_dlopen) is to look for files in the
// installation directory of blaze if the cwd doesn't work
// we don't search install dir if filename begins with '/'
// or './', but we do search install dir for '../' because
// "../lib/" or "../demo/" or "../etc/" are common
static char * blaze_exec_path
= NULL
;
FILE* SYSTEM_fopen (const char * filename
, const char * flags
)
fp
= fopen (filename
, flags
);
if (!fp
&& blaze_exec_path
&& !(filename
[0] == '/')
&& !(strncmp(filename
, "../", 3) == 0)) {
char * temp
= (char*) malloc (strlen (blaze_exec_path
)
+ strlen (filename
) + 1);
strcpy (temp
, blaze_exec_path
);
fp
= fopen (temp
, flags
);
int SYSTEM_open (const char * filename
, int oflag
)
fd
= open (filename
, oflag
);
if (fd
<0 && blaze_exec_path
&& !(filename
[0] == '/')
&& !(strncmp(filename
, "../", 3) == 0)) {
char * temp
= (char*) malloc (strlen (blaze_exec_path
)
+ strlen (filename
) + 1);
strcpy (temp
, blaze_exec_path
);
blaze_exec_path
= strdup (getexecname ());
if (blaze_exec_path
&& strlen(blaze_exec_path
) > 0) {
int i
= strlen (blaze_exec_path
) - 1;
while (i
>0 && blaze_exec_path
[i
] != '/') --i
;
blaze_exec_path
[i
+1] = '\0';
ui
->verbose("getexecname = \"%s\"\n", blaze_exec_path
);
ui
->error("SAM cannot determine its own install dir path, "
"\"load <filename>\" cannot search install dir for files\n");
///////////////////////////////////////////////////////////
void SYSTEM_set_memreserve (bool_t flag
)
bool_t
SYSTEM_get_memreserve()
void SYSTEM_cycle_delay (uint32_t cpuid
, uint32_t delay
)
Vcpu
*vcpu
= get_vcpu(cpuid
);
vcpu
->config
.delay
= delay
;
ui
->error("SYSTEM_cycle_delay: bad CPU id %d \n", cpuid
);
int SYSTEM_in_execution_driven_mode()
return g_vcpu
? g_vcpu
[0]->config
.execution_driven
: 0;
// must be called in response to a UI command, from the ui thread
void SYSTEM_enable_execution_driven_mode()
if (! IN_STOP_STATE(blaze_run_state
))
ui
->error("not in stop state \n");
if (SYSTEM_in_execution_driven_mode())
ui
->warning("enable_execution_driven_mode: exec-driven mode already enabled\n");
ui
->output("enabling exec-driven mode. Setting numthreads to 1\n");
for(int i
= 0; i
<= g_vcpu_id_max
; i
++)
Vcpu
*vcpu
= get_vcpu(i
);
vcpu
->config
.execution_driven
= 1;
} // void VCPU_Config::enable_execution_driven_mode()
void SYSTEM_disable_execution_driven_mode()
for(int i
= 0; i
<= g_vcpu_id_max
; i
++)
Vcpu
*vcpu
= get_vcpu(i
);
vcpu
->config
.execution_driven
= 0;
} // void VCPU_Config::disable_execution_driven_mode()
cpuT
*SYSTEM_cpu_by_sid(int n
)
void * SYSTEM_is_ready ()
BLAZE_STOP(blaze_run_state
); // transition from INVALID to STOP !!!
mutex_init (&ui_lock
, USYNC_THREAD
, 0);
cond_init (&ui_cond
, USYNC_THREAD
, 0);
//////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////
// External interrupt delivery. This function is being called
// by SCHIZO as well as in other CPU (xcalls) in order to send INTR.
void SYSTEM_interrupt_by_sid(int dst_aid
, int src_aid
, intrT
*intr
)
Vcpu
*vcpu
= get_vcpu(dst_aid
);
vcpu
->interrupt ( intr
);
static sint64_t system_intervalstart_usecs
= 0;
static sint64_t system_intervallength_usecs
= 0;
static sint64_t system_interval_sequencenum
= 0;
bool SYSTEM_is_sync_on ()
if (IN_GTWAIT_STATE (blaze_run_state
) || IN_GTSTEP_STATE (blaze_run_state
))
void SYSTEM_mark_intervalstart (sint64_t usecs
, uint64_t seqnum
)
system_intervalstart_usecs
= SYSTEM_get_global_time();
system_intervallength_usecs
= usecs
;
system_interval_sequencenum
= seqnum
;
void SYSTEM_mark_intervalstop ()
sint64_t
SYSTEM_get_sequencenum ()
return system_interval_sequencenum
;
int64_t SYSTEM_get_time (timewhence_t whence
/*= TW_CURRENT*/)
if (whence
== TW_CURRENT
)
return SYSTEM_get_global_time();
else if (whence
== TW_INTERVAL
)
return SYSTEM_get_global_time() - system_intervalstart_usecs
;
else if (whence
== TW_MARK
)
return system_intervalstart_usecs
;
else if (whence
== TW_LENGTH
)
return system_intervallength_usecs
;
extern doneftn_t
volatile wrkthdCBFunc
;
extern void * volatile wrkthdCBArg
;
extern sema_t wrkthdDONE
;
static void check_mips_stickfreq()
// stickfreq not being set will cause kernel panic, so error anyway.
if (the_arch
.stick_freq
== 0){
ui
->error("stickfreq not conf'ed. Add conf stickfreq <value> in rc file.\n");
if (the_arch
.mips
== 0) {
// if running from a checkpoint, then walk around
if (BLAZE_restore_from_checkpoint ()) {
// calculate the mips from the loopticks, stickincr
// recalculate to reflect changes in loopticks/stickincr/etc
the_arch
.mips
= ((the_arch
.loopticks
* the_arch
.stick_freq
)
/ the_arch
.stickincr
) / 1000000ULL;
the_arch
.umips
= the_arch
.kmips
= the_arch
.mips
;
ui
->error("mips not conf'ed, exit. Add conf mips <value> in rc file.\n");
void SYSTEM_kick_usecs (int64_t nusecs
)
WorkerThread::create_worker_threads (SYSTEM_get_ncpu(),SYSTEM_get_cpus_per_thread(),\
SYSTEM_get_numthreads());
while (sema_trywait (&wrkthdDONE
) == 0) ; // "sema_reset()"
if (SYSTEM_in_execution_driven_mode()) {
WorkerThread::kick_stepc(nusecs
* (g_vcpu
[0]->config
.cpufreq
/ 1000000));
WorkerThread::kick_stept(nusecs
);
void SYSTEM_kick_instrs (int64_t ninstrs
)
WorkerThread::create_worker_threads (SYSTEM_get_ncpu(),SYSTEM_get_cpus_per_thread(),\
SYSTEM_get_numthreads());
while (sema_trywait (&wrkthdDONE
) == 0) ; // "sema_reset()"
WorkerThread::kick_stepi(ninstrs
);
void SYSTEM_kick_cycles(int64_t ncycles
)
WorkerThread::create_worker_threads(SYSTEM_get_ncpu(), SYSTEM_get_cpus_per_thread(),
SYSTEM_get_numthreads());
while (sema_trywait (&wrkthdDONE
) == 0) ; // "sema_reset()"
WorkerThread::kick_stepc(ncycles
);
SYSTEM_kick_with_callback (int64_t nusecs
, doneftn_t callback
)
// only used by G-T-Sync, hence only a `usecs' version
SYSTEM_kick_usecs (nusecs
);
// -------- Time and Events ---------------------------------------------------
void SYSTEM_register_event (
EventFunc_T
* callbackfunc
, void * arg1
, void * arg2
,
UnloadFunc_T
* unloadfunc
,
const char * debugstring
)
WorkerThread::registerEvent(stime
, callbackfunc
, arg1
, arg2
,
unloadfunc
, debugstring
);
int eventque_ui_cmds (void*, int argc
, char **argv
)
if (argc
> 1 && strcmp (argv
[1], "debug") == 0) {
EventQue::debug
= strtol (argv
[2], NULL
, 0);
ui
->verbose("events debug = %d\n", EventQue::debug
);
WorkerThread::doEventquePrint ();
int64_t SYSTEM_get_ticks () // for perf_ui_cmd() only.!.
return WorkerThread::get_ticks();
uint64_t SYSTEM_get_globaltick_per_cpu () // for fc device, deprecated
return WorkerThread::get_ticks(); // also deprecated
uint64_t SYSTEM_get_global_time() // in MicroSecs, always !!!
return WorkerThread::get_time();
// ========================================================================== {
// The routines below are being called in context of UI thread !!
/**********************************************************
* Blaze Run State Diagram for UI commands:
* +--------+ "stepi" +--------+
* +--------+ "stop" +--------+
* "resume"| |"stop", CTRL-C
* +--------+ "stept" +--------+
* Note: we call device start/stop_action() when leaving/entering
* the STOP state, but not when cycling between the GT* states.
**********************************************************/
void SYSTEM_ss_register (ss_action stop
, ss_action restart
, void* d
)
SS_entry
*pentry
= (SS_entry
*) calloc (1, sizeof(SS_entry
));
pentry
->stop_action
= stop
;
pentry
->start_action
= restart
;
ui
->fatal("internal error (psys is not init yet)\n");
pentry
->next
= psys
->ss_head
;
static void SYSTEM_device_stop_action()
for (SS_entry
*pentry
= psys
->ss_head
; pentry
; pentry
= pentry
->next
) {
pentry
->stop_action (pentry
->client_data
);
static void SYSTEM_devices_start_action()
for (SS_entry
*pentry
= psys
->ss_head
; pentry
; pentry
= pentry
->next
) {
if (pentry
->start_action
)
pentry
->start_action (pentry
->client_data
);
// put the cpu-sims into async run mode ----------------------------------
if (! IN_STOP_STATE(blaze_run_state
))
BLAZE_RUN(blaze_run_state
);
SYSTEM_kick_usecs (1ULL <<48/*infinity*/); // Start cpus
SYSTEM_devices_start_action();
// The stop, stepi, stepc, and syncoff all end with a call to
// SYSTEM_wait_stop() which will wait for the workerthread to
// finish and and then stop the rest.
static void SYSTEM_wait_stop()
static bool sema_wait_pending
= false;
// Only one thread can be waiting in the semaphore for the
// worker threads to stop. So when a wait is pending then we
// just synchronize the return when stop really occurs.
while (sema_wait_pending
)
cond_wait(&ui_cond
,&ui_lock
);
sema_wait_pending
= true;
// We know that we get here holding the ui_lock. We wait here
// for the worker threads to finish. While we wait we release
// the ui lock. If we don't release the lock then we have a
// potential deadlock situation where stop is holding the lock
// and a probe action is waiting for the lock - blocking the
// workerthread from stopping.
sema_wait (&wrkthdDONE
); // ------ wait for all to finish ------
sema_wait_pending
= false;
cond_broadcast(&ui_cond
);
// cpu threads stop first to make io stop safe logic easy
SYSTEM_device_stop_action();
BLAZE_CLEAR(blaze_stop_request
); // Reset stop request if any pending
BLAZE_STOP(blaze_run_state
); // Reset
update_remote_ui(); // signal stop to remote debug client
// stop the async run mode ----------------------------------
/* gtwait means we're already stopped !! */
if (IN_GTWAIT_STATE (blaze_run_state
)) {
SYSTEM_device_stop_action();
BLAZE_STOP(blaze_run_state
);
if (IN_STOP_STATE (blaze_run_state
))
BLAZE_STOP(blaze_stop_request
);
// run the cpu-sims synchronously (ui waits) --------------------------------
void SYSTEM_stepi_UI (int64_t ni
)
assert(IN_STOP_STATE(blaze_run_state
));
BLAZE_STEP(blaze_run_state
);
SYSTEM_devices_start_action();
void SYSTEM_stepc_UI (int64_t nc
)
assert(IN_STOP_STATE(blaze_run_state
));
BLAZE_STEP(blaze_run_state
);
SYSTEM_devices_start_action();
// -------------------- a Global-Time-Sync interval ---------------------
static void SYSTEM_stept_callback (void * arg
);
static doneftn_t stept_callback_ftn
;
static void * stept_callback_arg
;
void SYSTEM_stept_UI (int64_t usecs
, int64_t seqnum
, doneftn_t callback
)
if (!IN_GTWAIT_STATE(blaze_run_state
))
SYSTEM_mark_intervalstart (usecs
, seqnum
); // MARK BEGIN <---
BLAZE_GTSTEP(blaze_run_state
); // Set
stept_callback_ftn
= callback
;
stept_callback_arg
= NULL
;
SYSTEM_kick_with_callback (usecs
, SYSTEM_stept_callback
); // Start cpus
// N.B. `devices' are started at syncON, not here. // devices
static void SYSTEM_stept_callback (void * /* arg */)
BLAZE_GTWAIT(blaze_run_state
); // Reset
// N.B. `devices' are stopped at syncOFF, not here. // devices
SYSTEM_mark_intervalstop (); // MARK END <---
doneftn_t FTN
= stept_callback_ftn
;
stept_callback_ftn
= NULL
;
(*FTN
) (stept_callback_arg
);
// "sync on" ----------------------------------------------------------
if (!IN_STOP_STATE(blaze_run_state
))
SYSTEM_devices_start_action();
BLAZE_GTWAIT(blaze_run_state
);
// "sync off" ----------------------------------------------------------
void SYSTEM_syncoff_UI ()
if (!IN_SYNC_STATE(blaze_run_state
))
if (IN_GTSTEP_STATE(blaze_run_state
)) {
BLAZE_STOP(blaze_stop_request
); // Request halt
assert(IN_GTWAIT_STATE(blaze_run_state
));
SYSTEM_device_stop_action();
BLAZE_STOP(blaze_run_state
); // Reset
// quit,exit,terminate,... ----------------------------------------------------
// this is being call from entirely too many places...
ui
->output("quitting ...\n");
// devices/scsi_disk.cc should not be calling this...
///////////////////////////////////////////////
void SYSTEM_ss_unregister (void *d
)
SS_entry
*pentry
= psys
->ss_head
;
if (pentry
->client_data
== d
) {
prev
->next
= pentry
->next
;
psys
->ss_head
= pentry
->next
;
bool_t
SYSTEM_is_stopped ()
return IN_STOP_STATE(blaze_run_state
) ? TRUE
: FALSE
;
bool_t
SYSTEM_is_running ()
return ANY_RUNNING_STATE(blaze_run_state
) ? TRUE
: FALSE
;
bool_t
SYSTEM_is_notready ()
return blaze_run_state
== e_BLAZE_INVALID
? TRUE
: FALSE
;
// ========================================================================== }
// ========================================================================== {
extern void write_scalar_64 (FILE *fp
, const char * name
, uint64_t v
);
extern void write_scalar_32 (FILE *fp
, const char * name
, uint32_t v
);
extern void write_string (FILE *fp
, const char * name
, char *s
);
extern bool_t
read_scalar_64 (FILE *fp
, const char * name
, uint64_t *v
);
extern bool_t
read_scalar_32 (FILE *fp
, const char * name
, uint32_t *v
);
extern char* read_string (FILE *fp
, const char * name
, int , char *s
);
extern char* read_string_2 (FILE *fp
, const char * name
, const char * alt_name
, int , char *s
);
write_scalar_64 (fp
, "global_tick", global_tick
);
write_scalar_32 (fp
, "numcpus", the_arch
.numcpus
);
write_scalar_32 (fp
, "nwins", the_arch
.nwins
);
write_scalar_64 (fp
, "ramsize", the_arch
.ramsize
);
write_scalar_32 (fp
, "tlbsize", the_arch
.tlbsize
);
write_scalar_32 (fp
, "loopticks", the_arch
.loopticks
);
write_scalar_32 (fp
, "loopticks_cp", the_arch
.loopticks_cp
);
write_scalar_32 (fp
, "stickincr", the_arch
.stickincr
);
write_scalar_32 (fp
, "cpus_per_thread", the_arch
.cpus_per_thread
);
write_scalar_64 (fp
, "cpu_freq", the_arch
.cpu_freq
);
write_scalar_64 (fp
, "stick_freq", the_arch
.stick_freq
);
write_scalar_32 (fp
, "arch_flags", the_arch
.arch_flags
);
write_string (fp
, "cputype", the_arch
.mmutype
);
write_string (fp
, "platform", the_arch
.platform
);
write_scalar_32 (fp
, "cpi", the_arch
.cpi
);
write_scalar_32 (fp
, "boot_ctrl_id", boot_ctrl_id
);
write_scalar_32 (fp
, "boot_target_id", boot_target_id
);
//write_scalar_32 (fp, "boot_disk_id", boot_disk_id);
write_scalar_32 (fp
, "boot_part_id", boot_part_id
);
write_scalar_32 (fp
, "numNICs", the_arch
.numNICs
);
write_scalar_32 (fp
, "numDCs", the_arch
.numDCs
); // number of disk controllers on pciA
write_scalar_64 (fp
, "mips", the_arch
.mips
);
write_scalar_64 (fp
, "umips", the_arch
.umips
);
write_scalar_64 (fp
, "kmips", the_arch
.kmips
);
write_scalar_32 (fp
, "roundrobin", the_arch
.roundrobin
);
SYSTEM_restore (FILE *fp
)
char line
[1000], temp
[1000];
if (fgets (line
, sizeof(line
), fp
) == NULL
)
else if (sscanf (line
, "arch_flags %i", &the_arch
.arch_flags
) == 1) ;
else if (sscanf (line
, "global_tick %lli", &global_tick
) == 1) ;
else if (sscanf (line
, "cpus_per_thread %i",&the_arch
.cpus_per_thread
)==1);
else if (sscanf (line
, "numcpus %i", &the_arch
.numcpus
) == 1) ;
else if (sscanf (line
, "nwins %i", &the_arch
.nwins
) == 1) ;
else if (sscanf (line
, "ramsize %lli", &the_arch
.ramsize
) == 1) ;
else if (sscanf (line
, "tlbsize %i", &the_arch
.tlbsize
) == 1) ;
else if (sscanf (line
, "loopticks %i", &the_arch
.loopticks
) == 1) ;
else if (sscanf (line
, "loopticks_cp %i", &the_arch
.loopticks_cp
)==1) ;
else if (sscanf (line
, "stickincr %i", &the_arch
.stickincr
) == 1) ;
else if (sscanf (line
, "cpu_freq %lli", &the_arch
.cpu_freq
) == 1) ;
else if (sscanf (line
, "stick_freq %lli", &the_arch
.stick_freq
) == 1) ;
else if (sscanf (line
, "cpi %i", &the_arch
.cpi
) == 1) ;
else if (sscanf (line
, "mips %lli", &the_arch
.mips
) == 1) {
the_arch
.umips
= the_arch
.kmips
= the_arch
.mips
; }
else if (sscanf (line
, "umips %lli", &the_arch
.umips
) == 1) ;
else if (sscanf (line
, "kmips %lli", &the_arch
.kmips
) == 1) ;
else if (sscanf (line
, "roundrobin %i", &the_arch
.roundrobin
) == 1) ;
else if (sscanf (line
, "boot_ctrl_id %i", &boot_ctrl_id
) == 1) ;
else if (sscanf (line
, "boot_target_id %i", &boot_target_id
) == 1) ;
else if (sscanf (line
, "boot_part_id %i", &boot_part_id
) == 1) ;
else if (sscanf (line
, "numNICs %i", &the_arch
.numNICs
) == 1) ;
else if (sscanf (line
, "numDCs %i", &the_arch
.numDCs
) == 1) ;
else if (sscanf (line
, "platform %s", &temp
[0]) == 1) {
the_arch
.platform
= strdup (temp
); }
else if (sscanf (line
, "cputype %s", &temp
[0]) == 1) {
the_arch
.mmutype
= strdup (temp
);
if (strcmp(the_arch
.mmutype
, "cheetah") == 0
|| strcmp(the_arch
.mmutype
, "spitfire") == 0)
ui
->verbose("restore: mmutype %s NG. with CHPLUS \n",
if (strcmp(the_arch
.mmutype
, "cheetahplus") == 0)
ui
->verbose("restore: mmutype %s NG. with CH \n",
else if (WorkerThread::restore(&line
[0]) == 1) ;
ui
->error("restore: unrecognized: %s\n", line
);
if (restore_v4_dump() && the_arch
.mips
== 0) {
// need non-zero values for all of these v4 config values
if (the_arch
.loopticks
&& the_arch
.stickincr
&& the_arch
.stick_freq
) {
int64_t mips
= (( (the_arch
.stick_freq
* the_arch
.loopticks
)
/ the_arch
.stickincr
) / 1000000LL);
ui
->verbose("mips computed from v4 stick_freq*loopticks/stickincr/1M"
" = %lld\n", the_arch
.mips
);
// hmmm, insufficient data, but this can't happen...?...
// ========================================================================== {
uint8_t SYSTEM_get_dc_num()
return (the_arch
.numDCs
);
uint8_t SYSTEM_get_nic_num()
return (the_arch
.numNICs
);
bool_t
SYSTEM_chplus_mmu ()
extern int get_wrdiskdelay();
int SYSTEM_get_wrdiskdelay()
return get_wrdiskdelay();
extern int get_diskdelay();
int SYSTEM_get_diskdelay()
int SYSTEM_get_loopticks ()
return the_arch
.loopticks
;
int SYSTEM_get_stickincr ()
return the_arch
.stickincr
;
uint64_t SYSTEM_get_stickfreq()
return the_arch
.stick_freq
;
uint64_t SYSTEM_get_cpufreq()
return the_arch
.cpu_freq
;
const char* SYSTEM_get_mmutypeS()
const char* SYSTEM_get_cputypeS()
const char* SYSTEM_get_infostr ()
return BLAZEVERSION_STRING
;
char * SYSTEM_get_version ()
return (char*)BLAZEVERSION_STRING
;
uint32_t SYSTEM_get_ncpu ()
uint32_t SYSTEM_get_ncores()
// this function is invoked in rs2blaze, do not remove it
// unless the caller in rs2blaze is modified accordingly.
return the_arch
.numcores
;
ui
->warning("SYSTEM_get_ncores call invalid unless in cmp_mode\n");
//assert(0); // DEVENDRA commented this out
int SYSTEM_get_cpus_per_thread ()
return the_arch
.cpus_per_thread
;
int SYSTEM_get_numthreads ()
return the_arch
.numthreads
;
int SYSTEM_get_blockmp ()
return the_arch
.block_mp
;
bool_t
SYSTEM_get_ce_enable_flag ()
void SYSTEM_set_ce_enable_flag (bool_t flag
)
bool_t
SYSTEM_get_scsi_disk_enable_flag ()
return scsi_disk_enable_flag
;
void SYSTEM_set_scsi_disk_enable_flag (bool_t flag
)
scsi_disk_enable_flag
= flag
;
bool_t
SYSTEM_get_scsi_boot_enable_flag ()
return scsi_boot_enable_flag
;
void SYSTEM_set_scsi_boot_enable_flag (bool_t flag
)
scsi_boot_enable_flag
= flag
;
// to enable boot from any schizo and bus
void SYSTEM_set_boot_aid_bus(unsigned char aid
, unsigned char bus
)
scsi_boot_enable_flag
+= (bus
<< 7) | (aid
<< 4);
bool_t
SYSTEM_get_fc_disk_enable_flag ()
return fc_disk_enable_flag
;
void SYSTEM_set_fc_disk_enable_flag (bool_t flag
)
fc_disk_enable_flag
= flag
;
bool_t
SYSTEM_get_fc_boot_enable_flag ()
return fc_boot_enable_flag
;
void SYSTEM_set_fc_boot_enable_flag (bool_t flag
)
fc_boot_enable_flag
= flag
;
bool_t
SYSTEM_is_serengeti()
if (the_arch
.platform
== NULL
)
if (strcmp (the_arch
.platform
, "SUNW,Sun-Fire") == NULL
)
if (the_arch
.platform
== NULL
)
if(strcmp (the_arch
.platform
, "SUNW,Sun-Fire-480R") == NULL
)
// ========================================================================== }
// ============================================================================
// HOSTCONFIG property lookup table
// at the moment this is simply {"name", "value"} pairs, there is not yet
// any "name.subname.subsubname.etc..." convention,
// also note that the caller must ensure the strings are in stable memory,
// here we only save pointers...
#include <map> // Oh No Mr Bill,... STL ...!!!...
class str_less
: public std::binary_function
<const char*A
, const char*B
, bool> {
bool operator () (const char * A
, const char * B
) const {
return strcmp (A
, B
) < 0;
typedef std::map
<const char *, const char *, str_less
> Dictionary
;
class str_less
: public std::binary_function
<const char* _x
, const char* _y
, bool> {
bool operator () (const char* _x
, const char* _y
) const {
return (strcmp (_x
, _y
) < 0);
typedef std::map
<const char*, key
, str_less
> Dictionary
;
bool_t
SYSTEM_isset_hostconfig (const char * configname
)
hostconfig
= new Dictionary
;
return hostconfig
->count(configname
) != 0;
// returns config-value, given config-name, simple dictionary/map lookup.
const char * SYSTEM_get_hostconfig (const char * configname
)
hostconfig
= new Dictionary
;
if (hostconfig
->count (configname
) != 0) {
return (*hostconfig
)[ configname
];
// used by ... to initially record the hostconfig info
void SYSTEM_set_hostconfig (const char * configname
, const char * configvalue
)
hostconfig
= new Dictionary
;
(*hostconfig
)[ configname
] = configvalue
;
void SYSTEM_dump_hostconfig (FILE * f
)
void SYSTEM_set_goodtrap_pc(uint64_t pc_va
) {
uint64_t SYSTEM_get_goodtrap_pc() {
void SYSTEM_set_badtrap_pc(uint64_t pc_va
) {
uint64_t SYSTEM_get_badtrap_pc() {
// used when restore from v4 and translate delaycount into usecs.
sint64_t
SYSTEM_Sticks2usecs (sint64_t sticks
)
* Time is by definition equal to (sticks / stick_frequency).
return (sint64_t
)((double)sticks
/ ((double)SYSTEM_get_stickfreq()/1000000.0));
// used when restore from v4 and translate delaycount from cycles into usecs.
sint64_t
SYSTEM_Ticks2usecs (sint64_t ticks
)
* Warning, ticks can be unreliable.
* Blaze re-computes ticks every time the user changes loopticks, or stickincr.
return (sint64_t
)((double)ticks
* ((double)SYSTEM_get_stickincr() / SYSTEM_get_loopticks())
/ ((double)SYSTEM_get_stickfreq() / 1000000.0));