Initial commit of OpenSPARC T2 architecture model.
[OpenSPARC-T2-SAM] / sam-t2 / sam / system / blaze / system.cc
CommitLineData
920dae64
AT
1// ========== Copyright Header Begin ==========================================
2//
3// OpenSPARC T2 Processor File: system.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) 2001, 2005 Sun Microsystems, Inc.
23 * All rights reserved.
24 */
25
26/* file layout, icqs:
27 * UICMDS (ie functions called by ui)
28 * DUMPRESTORE
29 * CPUACCESS (
30 * SYSCONF (legacy api, to be replace with real sysconf api soon...)
31 * HOSTCONFIG
32 */
33
34/* standard C includes */
35#include <assert.h>
36#include <stdio.h>
37#include <stdlib.h>
38#include <string.h>
39#include <synch.h>
40#include <thread.h>
41#include <unistd.h>
42
43#include <sys/types.h>
44#include <sys/stat.h>
45#include <fcntl.h>
46#include <sys/wait.h>
47
48
49/* project includes */
50#include "types.h"
51#include "blaze_globals.h"
52
53
54#include "system.h"
55#include "ui.h"
56#include "dr.h"
57
58#include "system_impl.h"
59#include "ui_utils.h"
60#include "workerthread.h"
61
62uint32_t boot_ctrl_id = 0;
63uint32_t boot_target_id = 0;
64uint32_t boot_part_id = 0;
65uint32_t boot_disk_id = 0;
66
67
68extern void term_console_destroy (); // defined in term.cc
69
70
71
72
73// ========================== GLOBAL VARIABLES ================================
74
75
76
77
78
79
80// BS flags. Majority of them are needed only within startp time
81//
82static bool_t ce_enable_flag = FALSE;
83static bool_t scsi_disk_enable_flag = FALSE;
84static bool_t scsi_boot_enable_flag = FALSE;
85static bool_t fc_disk_enable_flag = FALSE;
86static bool_t fc_boot_enable_flag = FALSE;
87
88static bool_t mem_reserve_flag = TRUE;
89
90
91SystemT the_sys = {0};
92SystemT *psys = &the_sys;
93
94
95uint64_t goodtrap_pc;
96uint64_t badtrap_pc;
97
98// The SAM UI is multi threaded; input can come from the user,
99// the global time sync or a remote debugger for example. Every
100// ui command needs to be executed whilst holding the lock. The
101// ui_lock_held booleans is added to help in asserting this.
102// The ui_cond variable is for synchronizing stop, see SYSTEM_wait_stop()
103
104static mutex_t ui_lock;
105static cond_t ui_cond;
106static bool ui_lock_held;
107
108// ============================================================================
109//
110// SYSTEM_open (like tracemod/mod_dlopen) is to look for files in the
111// installation directory of blaze if the cwd doesn't work
112//
113// we don't search install dir if filename begins with '/'
114// or './', but we do search install dir for '../' because
115// "../lib/" or "../demo/" or "../etc/" are common
116//
117
118static char * blaze_exec_path = NULL;
119
120
121FILE* SYSTEM_fopen (const char * filename, const char * flags)
122{
123 FILE * fp;
124 fp = fopen (filename, flags);
125 if (!fp && blaze_exec_path && !(filename[0] == '/')
126 && !(strncmp(filename, "../", 3) == 0)) {
127 char * temp = (char*) malloc (strlen (blaze_exec_path)
128 + strlen (filename) + 1);
129 strcpy (temp, blaze_exec_path);
130 strcat (temp, filename);
131 fp = fopen (temp, flags);
132 }
133 return fp;
134}
135
136
137int SYSTEM_open (const char * filename, int oflag)
138{
139 int fd;
140 fd = open (filename, oflag);
141 if (fd<0 && blaze_exec_path && !(filename[0] == '/')
142 && !(strncmp(filename, "../", 3) == 0)) {
143 char * temp = (char*) malloc (strlen (blaze_exec_path)
144 + strlen (filename) + 1);
145 strcpy (temp, blaze_exec_path);
146 strcat (temp, filename);
147 fd = open (temp, oflag);
148 }
149 return fd;
150}
151
152
153void init_SYSTEM_open ()
154{
155 blaze_exec_path = strdup (getexecname ());
156
157 if (blaze_exec_path && strlen(blaze_exec_path) > 0) {
158 int i = strlen (blaze_exec_path) - 1;
159 while (i>0 && blaze_exec_path[i] != '/') --i;
160 blaze_exec_path[i+1] = '\0';
161 } else {
162 ui->verbose("getexecname = \"%s\"\n", blaze_exec_path);
163 ui->error("SAM cannot determine its own install dir path, "
164 "\"load <filename>\" cannot search install dir for files\n");
165 }
166}
167
168
169///////////////////////////////////////////////////////////
170
171
172void SYSTEM_set_memreserve (bool_t flag)
173{
174 mem_reserve_flag = flag;
175}
176
177bool_t SYSTEM_get_memreserve()
178{
179 return mem_reserve_flag;
180}
181
182
183
184void SYSTEM_cycle_delay (uint32_t cpuid, uint32_t delay)
185{
186 Vcpu *vcpu = get_vcpu(cpuid);
187 if (vcpu) {
188 vcpu->config.delay = delay;
189 } else {
190 ui->error("SYSTEM_cycle_delay: bad CPU id %d \n", cpuid);
191 }
192}
193
194
195
196int SYSTEM_in_execution_driven_mode()
197{
198 return g_vcpu ? g_vcpu[0]->config.execution_driven : 0;
199}
200
201
202// must be called in response to a UI command, from the ui thread
203void SYSTEM_enable_execution_driven_mode()
204{
205 if (! IN_STOP_STATE(blaze_run_state))
206 {
207 ui->error("not in stop state \n");
208 return;
209 }
210
211 if (SYSTEM_in_execution_driven_mode())
212 {
213 ui->warning("enable_execution_driven_mode: exec-driven mode already enabled\n");
214 }
215 else
216 {
217 ui->output("enabling exec-driven mode. Setting numthreads to 1\n");
218
219 for(int i = 0; i <= g_vcpu_id_max; i++)
220 {
221 Vcpu *vcpu = get_vcpu(i);
222 if (!vcpu)
223 continue;
224
225 vcpu->config.execution_driven = 1;
226 }
227
228 the_arch.numthreads = 1;
229 cpu_enable_changed = 1;
230 }
231} // void VCPU_Config::enable_execution_driven_mode()
232
233
234
235void SYSTEM_disable_execution_driven_mode()
236{
237 for(int i = 0; i <= g_vcpu_id_max; i++)
238 {
239 Vcpu *vcpu = get_vcpu(i);
240 if (!vcpu)
241 continue;
242
243 vcpu->config.execution_driven = 0;
244 }
245 cpu_enable_changed = 1;
246} // void VCPU_Config::disable_execution_driven_mode()
247
248
249
250
251cpuT *SYSTEM_cpu_by_sid(int n)
252{
253 return get_vcpu(n);
254}
255
256
257
258void SYSTEM_unlock ()
259{
260}
261
262
263
264void * SYSTEM_is_ready ()
265{
266 return psys;
267}
268
269
270void SYSTEM_init(void)
271{
272 BLAZE_STOP(blaze_run_state); // transition from INVALID to STOP !!!
273
274 mutex_init (&ui_lock, USYNC_THREAD, 0);
275 cond_init (&ui_cond, USYNC_THREAD, 0);
276
277 ui_lock_held = false;
278}
279
280
281void SYSTEM_lock_UI()
282{
283 assert(!ui_lock_held);
284 mutex_lock (&ui_lock);
285 ui_lock_held = true;
286}
287
288void SYSTEM_unlock_UI()
289{
290 assert(ui_lock_held);
291 ui_lock_held = false;
292 mutex_unlock(&ui_lock);
293}
294
295//////////////////////////////////////////////////////////////////
296//////////////////////////////////////////////////////////////////
297
298//
299// External interrupt delivery. This function is being called
300// by SCHIZO as well as in other CPU (xcalls) in order to send INTR.
301//
302void SYSTEM_interrupt_by_sid(int dst_aid, int src_aid, intrT *intr)
303{
304 Vcpu *vcpu = get_vcpu(dst_aid);
305 if(vcpu)
306 vcpu->interrupt ( intr );
307}
308
309
310static sint64_t system_intervalstart_usecs = 0;
311static sint64_t system_intervallength_usecs = 0;
312static sint64_t system_interval_sequencenum = 0;
313
314bool SYSTEM_is_sync_on ()
315{
316 if (IN_GTWAIT_STATE (blaze_run_state) || IN_GTSTEP_STATE (blaze_run_state))
317 return true;
318 return false;
319}
320
321
322
323void SYSTEM_mark_intervalstart (sint64_t usecs, uint64_t seqnum)
324{
325 system_intervalstart_usecs = SYSTEM_get_global_time();
326 system_intervallength_usecs = usecs;
327 system_interval_sequencenum = seqnum;
328}
329
330
331void SYSTEM_mark_intervalstop ()
332{
333}
334
335sint64_t SYSTEM_get_sequencenum ()
336{
337 return system_interval_sequencenum;
338}
339
340
341int64_t SYSTEM_get_time (timewhence_t whence /*= TW_CURRENT*/)
342{
343 if (whence == TW_CURRENT)
344 return SYSTEM_get_global_time();
345
346 else if (whence == TW_INTERVAL)
347 return SYSTEM_get_global_time() - system_intervalstart_usecs;
348
349 else if (whence == TW_MARK)
350 return system_intervalstart_usecs;
351
352 else if (whence == TW_LENGTH)
353 return system_intervallength_usecs;
354
355 return 0ull;
356}
357
358extern doneftn_t volatile wrkthdCBFunc;
359extern void * volatile wrkthdCBArg;
360extern sema_t wrkthdDONE;
361
362static void check_mips_stickfreq()
363{
364 // stickfreq not being set will cause kernel panic, so error anyway.
365 if (the_arch.stick_freq == 0){
366 ui->error("stickfreq not conf'ed. Add conf stickfreq <value> in rc file.\n");
367 exit(1);
368 }
369
370 if (the_arch.mips == 0) {
371 // if running from a checkpoint, then walk around
372 if (BLAZE_restore_from_checkpoint ()) {
373 // calculate the mips from the loopticks, stickincr
374 // recalculate to reflect changes in loopticks/stickincr/etc
375 the_arch.mips = ((the_arch.loopticks * the_arch.stick_freq )
376 / the_arch.stickincr) / 1000000ULL;
377 the_arch.umips = the_arch.kmips = the_arch.mips;
378 }else{
379 ui->error("mips not conf'ed, exit. Add conf mips <value> in rc file.\n");
380 exit(1);
381 }
382 }
383}
384
385void SYSTEM_kick_usecs (int64_t nusecs)
386{
387 if (cpu_enable_changed)
388 WorkerThread::create_worker_threads (SYSTEM_get_ncpu(),SYSTEM_get_cpus_per_thread(),\
389 SYSTEM_get_numthreads());
390
391 while (sema_trywait (&wrkthdDONE) == 0) ; // "sema_reset()"
392
393 check_mips_stickfreq();
394
395 if (SYSTEM_in_execution_driven_mode()) {
396 WorkerThread::kick_stepc(nusecs * (g_vcpu[0]->config.cpufreq / 1000000));
397 } else {
398 WorkerThread::kick_stept(nusecs);
399 }
400}
401
402
403
404void SYSTEM_kick_instrs (int64_t ninstrs)
405{
406 if (cpu_enable_changed)
407 WorkerThread::create_worker_threads (SYSTEM_get_ncpu(),SYSTEM_get_cpus_per_thread(),\
408 SYSTEM_get_numthreads());
409
410 while (sema_trywait (&wrkthdDONE) == 0) ; // "sema_reset()"
411
412 check_mips_stickfreq();
413
414 WorkerThread::kick_stepi(ninstrs);
415}
416
417
418void SYSTEM_kick_cycles(int64_t ncycles)
419{
420 if (cpu_enable_changed)
421 WorkerThread::create_worker_threads(SYSTEM_get_ncpu(), SYSTEM_get_cpus_per_thread(),
422 SYSTEM_get_numthreads());
423
424 while (sema_trywait (&wrkthdDONE) == 0) ; // "sema_reset()"
425
426 check_mips_stickfreq();
427
428 WorkerThread::kick_stepc(ncycles);
429
430}
431
432
433
434void
435SYSTEM_kick_with_callback (int64_t nusecs, doneftn_t callback)
436{
437 // only used by G-T-Sync, hence only a `usecs' version
438
439 wrkthdCBFunc = callback;
440 wrkthdCBArg = NULL;
441 SYSTEM_kick_usecs (nusecs);
442}
443
444
445
446
447// -------- Time and Events ---------------------------------------------------
448// \___ microsecs.
449
450void SYSTEM_register_event (
451 uint64_t stime,
452 EventFunc_T * callbackfunc, void * arg1, void * arg2,
453 UnloadFunc_T * unloadfunc,
454 const char * debugstring)
455{
456 WorkerThread::registerEvent(stime, callbackfunc, arg1, arg2,
457 unloadfunc, debugstring);
458}
459
460
461int eventque_ui_cmds (void*, int argc, char **argv)
462{
463 if (argc > 1 && strcmp (argv[1], "debug") == 0) {
464 if (argc > 2) {
465 EventQue::debug = strtol (argv[2], NULL, 0);
466 }
467 ui->verbose("events debug = %d\n", EventQue::debug);
468 return 1;
469 }
470
471 WorkerThread::doEventquePrint ();
472 return 1;
473}
474
475
476int64_t SYSTEM_get_ticks () // for perf_ui_cmd() only.!.
477{
478 return WorkerThread::get_ticks();
479}
480
481
482uint64_t SYSTEM_get_globaltick_per_cpu () // for fc device, deprecated
483{
484 return WorkerThread::get_ticks(); // also deprecated
485}
486
487
488uint64_t SYSTEM_get_global_time() // in MicroSecs, always !!!
489{
490 return WorkerThread::get_time();
491}
492
493
494// ========================================================================== {
495// UICMDS
496//
497// The routines below are being called in context of UI thread !!
498//
499
500/**********************************************************
501 * Blaze Run State Diagram for UI commands:
502 *
503 *
504 * "run"
505 * +--------+ "stepi" +--------+
506 * | |- - - - - - ->>| |
507 * | STOP | | RUN |
508 * | |<<- - - - - - -| |
509 * +--------+ "stop" +--------+
510 * | ^ CTRL-C
511 * | ^
512 * | |
513 * "syncOn"| |"syncOff"
514 * "resume"| |"stop", CTRL-C
515 * | |
516 * V |
517 * V |
518 * +--------+ "stept" +--------+
519 * | |- - - - - - ->>| |
520 * | GTWAIT | | GTSTEP |
521 * | |<<- - - - - - -| |
522 * +--------+ +--------+
523 *
524 *
525 * Note: we call device start/stop_action() when leaving/entering
526 * the STOP state, but not when cycling between the GT* states.
527 *
528 **********************************************************/
529
530void SYSTEM_ss_register (ss_action stop, ss_action restart, void* d)
531{
532 SS_entry *pentry = (SS_entry*) calloc (1, sizeof(SS_entry));
533 pentry->stop_action = stop;
534 pentry->start_action = restart;
535 pentry->client_data = d;
536
537 if (psys == NULL) {
538 ui->fatal("internal error (psys is not init yet)\n");
539 exit (1);
540 }
541
542 pentry->next = psys->ss_head;
543 psys->ss_head = pentry;
544}
545
546static void SYSTEM_device_stop_action()
547{
548 for (SS_entry *pentry = psys->ss_head; pentry; pentry = pentry->next) {
549 if (pentry->stop_action)
550 pentry->stop_action (pentry->client_data);
551 }
552}
553
554static void SYSTEM_devices_start_action()
555{
556 for (SS_entry *pentry = psys->ss_head; pentry; pentry = pentry->next) {
557 if (pentry->start_action)
558 pentry->start_action (pentry->client_data);
559 }
560}
561
562// put the cpu-sims into async run mode ----------------------------------
563//
564void SYSTEM_run_UI ()
565{
566 assert(ui_lock_held);
567
568 if (! IN_STOP_STATE(blaze_run_state))
569 return;
570
571 BLAZE_RUN(blaze_run_state);
572
573 SYSTEM_kick_usecs (1ULL <<48/*infinity*/); // Start cpus
574 SYSTEM_devices_start_action();
575}
576
577// The stop, stepi, stepc, and syncoff all end with a call to
578// SYSTEM_wait_stop() which will wait for the workerthread to
579// finish and and then stop the rest.
580
581static void SYSTEM_wait_stop()
582{
583 static bool sema_wait_pending = false;
584
585 // Only one thread can be waiting in the semaphore for the
586 // worker threads to stop. So when a wait is pending then we
587 // just synchronize the return when stop really occurs.
588
589 if (sema_wait_pending)
590 {
591 while (sema_wait_pending)
592 cond_wait(&ui_cond,&ui_lock);
593 return;
594 }
595 sema_wait_pending = true;
596
597 // We know that we get here holding the ui_lock. We wait here
598 // for the worker threads to finish. While we wait we release
599 // the ui lock. If we don't release the lock then we have a
600 // potential deadlock situation where stop is holding the lock
601 // and a probe action is waiting for the lock - blocking the
602 // workerthread from stopping.
603
604 SYSTEM_unlock_UI();
605
606 sema_wait (&wrkthdDONE); // ------ wait for all to finish ------
607
608 SYSTEM_lock_UI();
609
610 sema_wait_pending = false;
611 cond_broadcast(&ui_cond);
612
613 // cpu threads stop first to make io stop safe logic easy
614 SYSTEM_device_stop_action();
615
616 BLAZE_CLEAR(blaze_stop_request); // Reset stop request if any pending
617 BLAZE_STOP(blaze_run_state); // Reset
618
619 update_remote_ui(); // signal stop to remote debug client
620}
621
622
623// stop the async run mode ----------------------------------
624//
625void SYSTEM_stop_UI ()
626{
627 assert(ui_lock_held);
628
629 /* gtwait means we're already stopped !! */
630 if (IN_GTWAIT_STATE (blaze_run_state)) {
631 SYSTEM_device_stop_action();
632 BLAZE_STOP(blaze_run_state);
633 return;
634 }
635 if (IN_STOP_STATE (blaze_run_state))
636 return;
637
638 BLAZE_STOP(blaze_stop_request);
639 SYSTEM_wait_stop();
640}
641
642// run the cpu-sims synchronously (ui waits) --------------------------------
643
644void SYSTEM_stepi_UI (int64_t ni)
645{
646 assert(IN_STOP_STATE(blaze_run_state));
647
648 BLAZE_STEP(blaze_run_state);
649
650 SYSTEM_kick_instrs(ni);
651 SYSTEM_devices_start_action();
652 SYSTEM_wait_stop();
653}
654
655
656void SYSTEM_stepc_UI (int64_t nc)
657{
658 assert(IN_STOP_STATE(blaze_run_state));
659
660 BLAZE_STEP(blaze_run_state);
661
662 SYSTEM_kick_cycles(nc);
663 SYSTEM_devices_start_action();
664 SYSTEM_wait_stop();
665}
666
667
668// -------------------- a Global-Time-Sync interval ---------------------
669//
670extern "C" {
671static void SYSTEM_stept_callback (void * arg);
672};
673
674static doneftn_t stept_callback_ftn;
675static void * stept_callback_arg;
676
677void SYSTEM_stept_UI (int64_t usecs, int64_t seqnum, doneftn_t callback)
678{
679 assert(ui_lock_held);
680
681 if (!IN_GTWAIT_STATE(blaze_run_state))
682 return;
683
684 SYSTEM_mark_intervalstart (usecs, seqnum); // MARK BEGIN <---
685
686 BLAZE_GTSTEP(blaze_run_state); // Set
687
688 stept_callback_ftn = callback;
689 stept_callback_arg = NULL;
690 SYSTEM_kick_with_callback (usecs, SYSTEM_stept_callback); // Start cpus
691
692 // N.B. `devices' are started at syncON, not here. // devices
693}
694
695extern "C" {
696static void SYSTEM_stept_callback (void * /* arg */)
697{
698 BLAZE_GTWAIT(blaze_run_state); // Reset
699
700 // N.B. `devices' are stopped at syncOFF, not here. // devices
701
702 SYSTEM_mark_intervalstop (); // MARK END <---
703
704 doneftn_t FTN = stept_callback_ftn;
705 if (FTN != NULL) {
706 stept_callback_ftn = NULL;
707 (*FTN) (stept_callback_arg);
708 }
709}
710};
711
712
713// "sync on" ----------------------------------------------------------
714//
715void SYSTEM_syncon_UI ()
716{
717 assert(ui_lock_held);
718
719 if (!IN_STOP_STATE(blaze_run_state))
720 return;
721
722 SYSTEM_devices_start_action();
723 BLAZE_GTWAIT(blaze_run_state);
724}
725
726
727// "sync off" ----------------------------------------------------------
728//
729void SYSTEM_syncoff_UI ()
730{
731 assert(ui_lock_held);
732
733 if (!IN_SYNC_STATE(blaze_run_state))
734 return;
735
736 if (IN_GTSTEP_STATE(blaze_run_state)) {
737 BLAZE_STOP(blaze_stop_request); // Request halt
738 SYSTEM_wait_stop();
739 return;
740 }
741
742 assert(IN_GTWAIT_STATE(blaze_run_state));
743 SYSTEM_device_stop_action();
744 BLAZE_STOP(blaze_run_state); // Reset
745}
746
747
748
749// quit,exit,terminate,... ----------------------------------------------------
750
751// this is being call from entirely too many places...
752void quit_simulation ()
753{
754
755#ifdef V5_FAKEPROM
756 term_console_destroy ();
757#endif
758
759
760 if ( mm1 != NULL )
761 delete mm1;
762
763 ui->output("quitting ...\n");
764 exit (0);
765}
766
767// devices/scsi_disk.cc should not be calling this...
768void SYSTEM_quit ()
769{
770 quit_simulation();
771 exit (0);
772}
773
774void SYSTEM_quit_UI ()
775{
776 quit_simulation();
777 exit (0);
778}
779
780
781///////////////////////////////////////////////
782
783void SYSTEM_ss_unregister (void *d)
784{
785 if (psys) {
786 SS_entry *pentry = psys->ss_head;
787 SS_entry *prev = NULL;
788 while (pentry) {
789 if (pentry->client_data == d) {
790 if (prev)
791 prev->next = pentry->next;
792 else
793 psys->ss_head = pentry->next;
794 free(pentry);
795 pentry = psys->ss_head;
796 prev = NULL;
797 }
798 else {
799 prev = pentry;
800 pentry = pentry->next;
801 }
802 }
803 }
804}
805
806
807
808
809bool_t SYSTEM_is_stopped ()
810{
811 return IN_STOP_STATE(blaze_run_state) ? TRUE : FALSE;
812}
813
814
815bool_t SYSTEM_is_running ()
816{
817 return ANY_RUNNING_STATE(blaze_run_state) ? TRUE : FALSE;
818}
819
820
821bool_t SYSTEM_is_notready ()
822{
823 return blaze_run_state == e_BLAZE_INVALID ? TRUE : FALSE;
824}
825
826
827
828// ========================================================================== }
829
830
831
832
833
834
835
836// ========================================================================== {
837// DUMPRESTORE
838
839
840extern void write_scalar_64 (FILE *fp, const char * name, uint64_t v);
841extern void write_scalar_32 (FILE *fp, const char * name, uint32_t v);
842extern void write_string (FILE *fp, const char * name, char *s);
843extern bool_t read_scalar_64 (FILE *fp, const char * name, uint64_t *v);
844extern bool_t read_scalar_32 (FILE *fp, const char * name, uint32_t *v);
845extern char* read_string (FILE *fp, const char * name, int , char *s);
846extern char* read_string_2 (FILE *fp, const char * name, const char * alt_name, int , char *s);
847
848
849
850void
851SYSTEM_dump (FILE *fp)
852{
853 write_scalar_64 (fp, "global_tick", global_tick);
854 write_scalar_32 (fp, "numcpus", the_arch.numcpus);
855 write_scalar_32 (fp, "nwins", the_arch.nwins);
856 write_scalar_64 (fp, "ramsize", the_arch.ramsize);
857 write_scalar_32 (fp, "tlbsize", the_arch.tlbsize);
858 write_scalar_32 (fp, "loopticks", the_arch.loopticks);
859 write_scalar_32 (fp, "loopticks_cp", the_arch.loopticks_cp);
860 write_scalar_32 (fp, "stickincr", the_arch.stickincr);
861 write_scalar_32 (fp, "cpus_per_thread", the_arch.cpus_per_thread);
862 write_scalar_64 (fp, "cpu_freq", the_arch.cpu_freq);
863 write_scalar_64 (fp, "stick_freq", the_arch.stick_freq);
864 write_scalar_32 (fp, "arch_flags", the_arch.arch_flags);
865 write_string (fp, "cputype", the_arch.mmutype);
866 write_string (fp, "platform", the_arch.platform);
867 write_scalar_32 (fp, "cpi", the_arch.cpi);
868 write_scalar_32 (fp, "boot_ctrl_id", boot_ctrl_id);
869 write_scalar_32 (fp, "boot_target_id", boot_target_id);
870 //write_scalar_32 (fp, "boot_disk_id", boot_disk_id);
871 write_scalar_32 (fp, "boot_part_id", boot_part_id);
872 write_scalar_32 (fp, "numNICs", the_arch.numNICs);
873 write_scalar_32 (fp, "numDCs", the_arch.numDCs); // number of disk controllers on pciA
874 write_scalar_64 (fp, "mips", the_arch.mips);
875 write_scalar_64 (fp, "umips", the_arch.umips);
876 write_scalar_64 (fp, "kmips", the_arch.kmips);
877 write_scalar_32 (fp, "roundrobin", the_arch.roundrobin);
878 WorkerThread::dump(fp);
879}
880
881
882
883
884bool_t
885SYSTEM_restore (FILE *fp)
886{
887 char line[1000], temp[1000];
888
889 do {
890 if (fgets (line, sizeof(line), fp) == NULL)
891 break;
892
893 else if (sscanf (line, "arch_flags %i", &the_arch.arch_flags) == 1) ;
894 else if (sscanf (line, "global_tick %lli", &global_tick) == 1) ;
895 else if (sscanf (line, "cpus_per_thread %i",&the_arch.cpus_per_thread)==1);
896 else if (sscanf (line, "numcpus %i", &the_arch.numcpus) == 1) ;
897
898 else if (sscanf (line, "nwins %i", &the_arch.nwins) == 1) ;
899 else if (sscanf (line, "ramsize %lli", &the_arch.ramsize) == 1) ;
900 else if (sscanf (line, "tlbsize %i", &the_arch.tlbsize) == 1) ;
901
902 else if (sscanf (line, "loopticks %i", &the_arch.loopticks) == 1) ;
903 else if (sscanf (line, "loopticks_cp %i", &the_arch.loopticks_cp)==1) ;
904 else if (sscanf (line, "stickincr %i", &the_arch.stickincr) == 1) ;
905 else if (sscanf (line, "cpu_freq %lli", &the_arch.cpu_freq) == 1) ;
906 else if (sscanf (line, "stick_freq %lli", &the_arch.stick_freq) == 1) ;
907 else if (sscanf (line, "cpi %i", &the_arch.cpi) == 1) ;
908 else if (sscanf (line, "mips %lli", &the_arch.mips) == 1) {
909 the_arch.umips = the_arch.kmips = the_arch.mips; }
910 else if (sscanf (line, "umips %lli", &the_arch.umips) == 1) ;
911 else if (sscanf (line, "kmips %lli", &the_arch.kmips) == 1) ;
912
913 else if (sscanf (line, "roundrobin %i", &the_arch.roundrobin) == 1) ;
914
915 else if (sscanf (line, "boot_ctrl_id %i", &boot_ctrl_id) == 1) ;
916 else if (sscanf (line, "boot_target_id %i", &boot_target_id) == 1) ;
917 else if (sscanf (line, "boot_part_id %i", &boot_part_id) == 1) ;
918
919 else if (sscanf (line, "numNICs %i", &the_arch.numNICs) == 1) ;
920 else if (sscanf (line, "numDCs %i", &the_arch.numDCs) == 1) ;
921
922
923 else if (sscanf (line, "platform %s", &temp[0]) == 1) {
924 the_arch.platform = strdup (temp); }
925
926 else if (sscanf (line, "cputype %s", &temp[0]) == 1) {
927 the_arch.mmutype = strdup (temp);
928#ifdef CHPLUS
929 if (strcmp(the_arch.mmutype, "cheetah") == 0
930 || strcmp(the_arch.mmutype, "spitfire") == 0)
931 ui->verbose("restore: mmutype %s NG. with CHPLUS \n",
932 the_arch.mmutype);
933#elif CH
934 if (strcmp(the_arch.mmutype, "cheetahplus") == 0)
935 ui->verbose("restore: mmutype %s NG. with CH \n",
936 the_arch.mmutype);
937#endif
938 }
939 else if (WorkerThread::restore(&line[0]) == 1) ;
940
941 else
942 ui->error("restore: unrecognized: %s\n", line);
943
944 } while (1) ;
945
946
947 if (restore_v4_dump() && the_arch.mips == 0) {
948
949 // need non-zero values for all of these v4 config values
950 //
951 if (the_arch.loopticks && the_arch.stickincr && the_arch.stick_freq) {
952
953 int64_t mips = (( (the_arch.stick_freq * the_arch.loopticks)
954 / the_arch.stickincr) / 1000000LL);
955
956 the_arch.mips = mips;
957 the_arch.umips = mips;
958 the_arch.kmips = mips;
959
960 ui->verbose("mips computed from v4 stick_freq*loopticks/stickincr/1M"
961 " = %lld\n", the_arch.mips);
962 }
963 //
964 // hmmm, insufficient data, but this can't happen...?...
965 }
966
967
968 return TRUE;
969}
970
971
972// ========================================================================== {
973// SYSCONF api routines
974//
975
976uint8_t SYSTEM_get_dc_num()
977{
978 return (the_arch.numDCs);
979}
980
981uint8_t SYSTEM_get_nic_num()
982{
983 return (the_arch.numNICs);
984}
985
986
987bool_t SYSTEM_chplus_mmu ()
988{
989#ifdef CHPLUS
990 return TRUE;
991#else
992 return FALSE;
993#endif
994}
995
996int SYSTEM_get_nwins()
997{
998 return the_arch.nwins;
999
1000}
1001
1002extern int get_wrdiskdelay();
1003int SYSTEM_get_wrdiskdelay()
1004{
1005 return get_wrdiskdelay();
1006}
1007
1008extern int get_diskdelay();
1009int SYSTEM_get_diskdelay()
1010{
1011 return get_diskdelay();
1012}
1013
1014int SYSTEM_get_loopticks ()
1015{
1016 return the_arch.loopticks;
1017}
1018
1019int SYSTEM_get_stickincr ()
1020{
1021 return the_arch.stickincr;
1022}
1023
1024uint64_t SYSTEM_get_stickfreq()
1025{
1026 return the_arch.stick_freq;
1027}
1028
1029uint64_t SYSTEM_get_cpufreq()
1030{
1031 return the_arch.cpu_freq;
1032}
1033
1034const char* SYSTEM_get_mmutypeS()
1035{
1036 return the_arch.mmutype;
1037}
1038
1039const char* SYSTEM_get_cputypeS()
1040{
1041 return the_arch.mmutype;
1042}
1043
1044int SYSTEM_get_tlbsize()
1045{
1046 return the_arch.tlbsize;
1047}
1048
1049
1050const char* SYSTEM_get_infostr ()
1051{
1052 return BLAZEVERSION_STRING;
1053}
1054
1055
1056
1057char * SYSTEM_get_version ()
1058{
1059 return (char*)BLAZEVERSION_STRING;
1060}
1061
1062uint32_t SYSTEM_get_ncpu ()
1063{
1064 return the_arch.numcpus;
1065}
1066
1067uint32_t SYSTEM_get_ncores()
1068{
1069 // this function is invoked in rs2blaze, do not remove it
1070 // unless the caller in rs2blaze is modified accordingly.
1071 if (the_arch.cmp_mode) {
1072 return the_arch.numcores;
1073 }
1074 else {
1075 ui->warning("SYSTEM_get_ncores call invalid unless in cmp_mode\n");
1076 return 0;
1077 //assert(0); // DEVENDRA commented this out
1078 }
1079}
1080
1081
1082int SYSTEM_get_cpus_per_thread ()
1083{
1084 return the_arch.cpus_per_thread;
1085}
1086
1087int SYSTEM_get_numthreads ()
1088{
1089 return the_arch.numthreads;
1090}
1091
1092int SYSTEM_get_skipmp ()
1093{
1094 return the_arch.skip_mp;
1095}
1096
1097int SYSTEM_get_blockmp ()
1098{
1099 return the_arch.block_mp;
1100}
1101
1102bool_t SYSTEM_get_ce_enable_flag ()
1103{
1104 return ce_enable_flag;
1105}
1106void SYSTEM_set_ce_enable_flag (bool_t flag)
1107{
1108 ce_enable_flag = flag;
1109}
1110
1111bool_t SYSTEM_get_scsi_disk_enable_flag ()
1112{
1113 return scsi_disk_enable_flag;
1114}
1115void SYSTEM_set_scsi_disk_enable_flag (bool_t flag)
1116{
1117 scsi_disk_enable_flag = flag;
1118}
1119bool_t SYSTEM_get_scsi_boot_enable_flag ()
1120{
1121 return scsi_boot_enable_flag;
1122}
1123void SYSTEM_set_scsi_boot_enable_flag (bool_t flag)
1124{
1125 scsi_boot_enable_flag = flag;
1126}
1127// to enable boot from any schizo and bus
1128void SYSTEM_set_boot_aid_bus(unsigned char aid, unsigned char bus)
1129{
1130 scsi_boot_enable_flag += (bus << 7) | (aid << 4);
1131}
1132bool_t SYSTEM_get_fc_disk_enable_flag ()
1133{
1134 return fc_disk_enable_flag;
1135}
1136void SYSTEM_set_fc_disk_enable_flag (bool_t flag)
1137{
1138 fc_disk_enable_flag = flag;
1139}
1140bool_t SYSTEM_get_fc_boot_enable_flag ()
1141{
1142 return fc_boot_enable_flag;
1143}
1144void SYSTEM_set_fc_boot_enable_flag (bool_t flag)
1145{
1146 fc_boot_enable_flag = flag;
1147}
1148
1149
1150bool_t SYSTEM_is_serengeti()
1151{
1152 if (the_arch.platform == NULL)
1153 return FALSE;
1154
1155 if (strcmp (the_arch.platform, "SUNW,Sun-Fire") == NULL)
1156 return TRUE;
1157 else
1158 return FALSE;
1159}
1160
1161bool_t SYSTEM_is_480R()
1162{
1163 if (the_arch.platform == NULL)
1164 return FALSE;
1165
1166 if(strcmp (the_arch.platform, "SUNW,Sun-Fire-480R") == NULL)
1167 return TRUE;
1168 else
1169 return FALSE;
1170}
1171
1172
1173// ========================================================================== }
1174
1175
1176
1177
1178
1179
1180// ============================================================================
1181//
1182// HOSTCONFIG property lookup table
1183//
1184// at the moment this is simply {"name", "value"} pairs, there is not yet
1185// any "name.subname.subsubname.etc..." convention,
1186//
1187// also note that the caller must ensure the strings are in stable memory,
1188// here we only save pointers...
1189//
1190
1191#include <map> // Oh No Mr Bill,... STL ...!!!...
1192
1193#if 1
1194class str_less : public std::binary_function<const char*A, const char*B, bool> {
1195public:
1196 bool operator () (const char * A, const char * B) const {
1197 return strcmp (A, B) < 0;
1198 }
1199};
1200
1201typedef std::map<const char *, const char *, str_less> Dictionary;
1202#else
1203class str_less : public std::binary_function <const char* _x, const char* _y, bool> {
1204public:
1205 bool operator () (const char* _x, const char* _y) const {
1206 return (strcmp (_x, _y) < 0);
1207 }
1208};
1209typedef std::map<const char*, key, str_less> Dictionary;
1210#endif
1211
1212Dictionary *hostconfig;
1213
1214
1215
1216bool_t SYSTEM_isset_hostconfig (const char * configname)
1217{
1218 if(!hostconfig){
1219 hostconfig = new Dictionary;
1220 }
1221 return hostconfig->count(configname) != 0;
1222}
1223
1224
1225// returns config-value, given config-name, simple dictionary/map lookup.
1226const char * SYSTEM_get_hostconfig (const char * configname)
1227{
1228 if(!hostconfig){
1229 hostconfig = new Dictionary;
1230 }
1231 if (hostconfig->count (configname) != 0) {
1232 return (*hostconfig)[ configname ];
1233 } else
1234 return NULL;
1235}
1236
1237
1238// used by ... to initially record the hostconfig info
1239void SYSTEM_set_hostconfig (const char * configname, const char * configvalue)
1240{
1241 if(!hostconfig){
1242 hostconfig = new Dictionary;
1243 }
1244 (*hostconfig)[ configname ] = configvalue;
1245}
1246
1247
1248// ... later ...
1249void SYSTEM_dump_hostconfig (FILE * f)
1250{
1251}
1252
1253
1254void SYSTEM_set_goodtrap_pc(uint64_t pc_va) {
1255 goodtrap_pc = pc_va;
1256}
1257
1258uint64_t SYSTEM_get_goodtrap_pc() {
1259 return goodtrap_pc;
1260}
1261
1262
1263void SYSTEM_set_badtrap_pc(uint64_t pc_va) {
1264 badtrap_pc = pc_va;
1265}
1266
1267uint64_t SYSTEM_get_badtrap_pc() {
1268 return badtrap_pc;
1269}
1270
1271// used when restore from v4 and translate delaycount into usecs.
1272sint64_t SYSTEM_Sticks2usecs (sint64_t sticks)
1273{
1274 /*
1275 * Time is by definition equal to (sticks / stick_frequency).
1276 */
1277 return (sint64_t)((double)sticks / ((double)SYSTEM_get_stickfreq()/1000000.0));
1278}
1279
1280// used when restore from v4 and translate delaycount from cycles into usecs.
1281sint64_t SYSTEM_Ticks2usecs (sint64_t ticks)
1282{
1283 /*
1284 * Warning, ticks can be unreliable.
1285 * Blaze re-computes ticks every time the user changes loopticks, or stickincr.
1286 */
1287 return (sint64_t)((double)ticks
1288 * ((double)SYSTEM_get_stickincr() / SYSTEM_get_loopticks())
1289 / ((double)SYSTEM_get_stickfreq() / 1000000.0));
1290}
1291
1292
1293/* -oOo-. */