// ========== Copyright Header Begin ==========================================
// OpenSPARC T2 Processor File: tm_api.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) 1991, 2001 Sun Microsystems, Inc.
#pragma ident "@(#)1.4 01/11/06 tm_api.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
#include "blaze_globals.h"
typedef void* TM_OPAQUE_DATA
;
LdmNode
*head_ldm
= NULL
; // The head of tracing LDM's
LdmNode
*head_spec_ldm
= NULL
; // The head of the list of BLAZE extensions
uint64_t tm_time_target
= 0xffffffffffffffffLLU
; // Is used for global time interval event handler
uint64_t tm_time_interval
= 0; // Is used for global time interval event handler
static LdmCmdNode
*head_ldm_cmd
= NULL
;
static char help_string
[] = "usage : mod load <type> <sofile> [<arglist>] | mod unload <name>\n\
type ::= analyzer | py | remote\n";
static char mmi_help_string_1
[] = "usage : ldm <dev name> <instance name> [<sofile><arglist>]";
static char mmi_help_string_2
[] = "usage : uldm <instance name>";
static char mmi_help_string_3
[] = "usage : ioa <ADDR1> <ADDR2> ";
static char mmi_help_string_4
[] = "usage : sysconf [-p <modpath> ] <modname> "
"[ <instance_name> [ args... ] ]";
static char mmi_help_string_5
[] = "usage : module [<modname> ...]";
//////////////////////////////////////////////////
//TODO: commands which require STOP
//////////////////////////////////////////////////
Ldm
* ldm_add_spec (char * name
, const char *soname
)
for (pnode
=head_spec_ldm
; pnode
!=NULL
; pnode
=pnode
->Next()) {
pldm
= pnode
->GetData ();
if (strcmp (name
, pldm
->name
) == NULL
) {
ui
->error("module %s - %s is already loaded !\n", name
, soname
);
if (pldm
->soname
&& (strcmp(soname
, pldm
->soname
) == NULL
)) {
ui
->error("module %s - %s is already loaded !\n", name
, soname
);
for (pnode
=head_spec_ldm
; pnode
!=NULL
; pnode
=pnode
->Next()) {
pldm
= pnode
->GetData ();
if (strcmp (name
, pldm
->name
) == NULL
) {
pnode
= LdmNode::CreateInstance ("MOD list");
ui
->error("Unable to load %s-%s : unable to allocate memory\n",
soname
? soname
: "**", name
);
pldm
= pnode
->GetData ();
pldm
->name
= (char*)strdup(name
);
pldm
->soname
= soname
? (char*)strdup(soname
) : NULL
;
for (ii
= 0; ii
< MAX_MP
; ii
++)
pldm
->memop
[ii
] = TM_CONST_BADMEM
;
pldm
->type
= TM_TYPE_EXT_UNKNOWN
;
LdmNode::AddTail (&head_spec_ldm
, pnode
);
//////////////////////////////////////////////////
static Ldm
* ldm_add (char * name
, const char *soname
)
for (pnode
=head_ldm
; pnode
; pnode
=pnode
->Next()) {
Ldm
* pldm
= pnode
->GetData();
if ((strcmp (name
, pldm
->name
) == NULL
) || (strcmp (soname
, pldm
->soname
) == NULL
)) {
ui
->error("module %s - %s is already loaded !\n", name
, soname
);
pnode
= LdmNode::CreateInstance ("MOD list");
ui
->error("Unable to register MODULE <%s>\n", name
);
Ldm
* pldm
= pnode
->GetData ();
pldm
->name
= (char*)strdup(name
);
pldm
->soname
= (char*)strdup(soname
);
for (ii
= 0; ii
< MAX_MP
; ii
++)
pldm
->memop
[ii
] = TM_CONST_BADMEM
;
pldm
->type
= TM_TYPE_LDM
;
LdmNode::AddTail (&head_ldm
, pnode
);
//////////////////////////////////////////////////////
static void ldm_delete_head ()
LdmNode::DeleteHead(&head_ldm
);
//////////////////////////////////////////////////////
void ldm_delete_head_spec ()
LdmNode::DeleteHead(&head_spec_ldm
);
//////////////////////////////////////////////////
static LdmCmd
* ldm_cmd_add (const char * name
, fn_ui_1 action1
, fn_ui_2 action2
)
LdmCmdNode
*pnode
= LdmCmdNode::CreateInstance ("CMD list");
ui
->error("Unable to register UI CMD <%s>\n", name
);
pldm_cmd
= pnode
->GetData ();
pldm_cmd
->name
= (char*)strdup(name
);
pldm_cmd
->cmd_action_1
= action1
;
pldm_cmd
->cmd_action_2
= action2
;
LdmCmdNode::AddHead (&head_ldm_cmd
, pnode
);
//////////////////////////////////////////////////
// ----------------------------------------------------------------------------
} mod_list
= {"$ORIGIN/../lib/", NULL
}; /* $ORIGIN always at end of search */
void mod_setdefault (char * subdir
) /* change "../lib/" to "../lib-obp/" */
{ /* in the $origin search path */
static char new_default
[PATH_MAX
];
sprintf (new_default
, "$ORIGIN/../%s/", subdir
);
mod_list
.name
= new_default
;
struct mod_list
* mod_head
= & mod_list
;
struct mod_list
* mod_tail
= & mod_list
;
// hmmm, shouldn't mod_addpath() do a "push" rather than an "insert"...
void mod_addpath (char * path
) /* subsequent dirs are inserted in */
{ /* front of the $ORIGIN last entry */
p
= (struct mod_list
*) malloc (sizeof (struct mod_list
));
if (mod_head
== mod_tail
) {
struct mod_list
* q
= mod_head
;
while (q
->next
!= mod_tail
) q
= q
->next
;
void * mod_dlopen (char * pathp
, char * fname
, int flags
)
if ( (fname
[0] == '/') /* don't mess with absolute file paths */
||(fname
[0] == '.' && fname
[1] == '/')
||(fname
[0] == '.' && fname
[1] == '.' && fname
[2] == '/')) {
sprintf (temp
, "%s", fname
);
result
= dlopen (temp
, flags
);
ui
->error("dlopen(%s)...\n %s\n", temp
, dlerr
);
} else if (pathp
!= NULL
) { /* use explicit path if provided */
sprintf (temp
, "%s/%s", pathp
, fname
);
result
= dlopen (temp
, flags
);
ui
->error("dlopen(%s)...\n %s\n", temp
, dlerr
);
} else { /* otherwise use searchlist */
for (struct mod_list
* p
= mod_head
; p
!= NULL
; p
= p
->next
) {
sprintf (temp
, "%s/%s", p
->name
, fname
);
result
= dlopen (temp
, flags
);
ui
->output("dlopen(%s): trying path %s...\n %s\n", fname
, temp
, dlerr
);
break; /* <-- found it ! */
ui
->verbose("dlopen(%s): loaded successfully\n", temp
);
ui
->error("dlopen(%s): failed (unresolved symbols or sysconf search path incorrect)\n",fname
);
// ----------------------------------------------------------------------------
// the following mod commands are currently supported:
// mod load <modname> <module.so>
const char mod_cmd_usage
[] = "Usage: mod <load|unload> <analyzer|py> [path/lib_name.so]\n";
static void * dlhandle
= NULL
;
void *(*vtracer_initfn
)(const char *) = NULL
;
void (*vtracer_finifn
)() = NULL
;
int init_tracer(char* fname
, char* modname
, void* lib_handle
)
// FIXME: currently, only one vtrace module is supported. 2005.09.27
if (g_vcpu
[0]->sys_intf
.vtrace
!= NULL
) {
ui
->error("a vtracer is already loaded. Only one vtracer is supported at this time\n");
vtracer_initfn
= (void *(*)(const char *)) dlsym(dlhandle
, "vtracer_init");
if (vtracer_initfn
== NULL
) {
ui
->error("mod load: could not find symbol vtracer_init() in %s: %s\n", fname
, dlerror());
vtracer_finifn
= (void (*)()) dlsym(dlhandle
, "vtracer_fini");
if (vtracer_finifn
== NULL
) {
ui
->error("mod load: could not find symbol vtracer_fini() in %s: %s\n", fname
, dlerror());
VTracer
* the_vtracer
= (VTracer
*) vtracer_initfn(modname
);
for (int i
=0; i
<=g_vcpu_id_max
; i
++)
Vcpu
*vcpu
= get_vcpu(i
);
vcpu
->sys_intf
.vtrace
= the_vtracer
;
vcpu
->config
.trace_on
= 1;
if (vtracer_finifn
!= NULL
) {
for (i
=0; i
<=g_vcpu_id_max
; i
++)
Vcpu
*vcpu
= get_vcpu(i
);
vcpu
->sys_intf
.vtrace
= NULL
;
vcpu
->config
.trace_on
= 0;
ui
->error("mod unload: no vtracer module is currently loaded\n");
///////////////////////////////////////////////////////////////////////////////
typedef int (*init_py_t
)(char*, char*, void*);
int init_py(char* fname
, char* modname
, void* lib_handle
)
init_py_t py_initfn
= (init_py_t
)dlsym(lib_handle
, "init_py_interface");
ui
->error("mod load: could not find symbol init_py_interface() in %s: %s\n", fname
, dlerror());
return py_initfn (fname
, modname
, lib_handle
);
///////////////////////////////////////////////////////////////////////
int mod_cmd_action(void*, int argc
, char **argv
)
ui
->output(mod_cmd_usage
);
if (strcmp(argv
[1], "load") == 0)
if (argc
!= 4 && argc
!= 3)
ui
->output(mod_cmd_usage
);
char suffixedname
[PATH_MAX
];
if (argc
== 4) fname
= argv
[3];
{ /* if there isn't an argv[3] then construct one from argv[2] */
sprintf (suffixedname
, "%s.so", argv
[2]);
if (ANY_RUNNING_STATE(blaze_run_state
)) {
ui
->error("not in stop state, use stop command first\n");
void *dlib_handle
= mod_dlopen (NULL
, fname
, RTLD_LAZY
|RTLD_GLOBAL
);
if (strcmp(modname
,"analyzer")==0)
return init_tracer(fname
, modname
, dlib_handle
);
else if(strcmp(modname
,"py")==0)
ui
->verbose("loading python interpreter....\n");
return init_py(fname
, modname
, dlib_handle
);
else if(strcmp(modname
,"remote")==0)
extern int init_remote_debugger_interface (char*, char*, void*);
ui
->verbose(" loading interface for remote debugger....\n");
return init_remote_debugger_interface(fname
, modname
, dlib_handle
);
else if (strcmp(modname
,"lib")==0)
ui
->verbose("lib %s was loaded. \n", fname
);
ui
->error(" %s : unknown module name\n%s\n", modname
, mod_cmd_usage
);
else if (strcmp(argv
[1], "unload") == 0)
ui
->output(mod_cmd_usage
);
if (strcmp(modname
,"analyzer")==0)
else if(strcmp(modname
,"py")==0)
ui
->error("cannot unload python interpreter module\n");
else if(strcmp(modname
,"remote")==0)
ui
->error("cannot unload remote interface module\n");
ui
->error("%s: unknown module name\n%s\n", modname
, mod_cmd_usage
);
ui
->error("Invalid argument %s\n%s\n", argv
[1], mod_cmd_usage
);
} // int mod_cmd_action(void*, int argc, char **argv)
//////////////////////////////////////////////////
int extra_cmd_action_1 (void*, int /*argc*/, char **argv
)
LdmCmdNode
*pnode
= head_ldm_cmd
;
for (;pnode
;pnode
= pnode
->Next()) {
pldm_cmd
= pnode
->GetData ();
if (strcmp(argv
[0], pldm_cmd
->name
) == NULL
) {
if (pldm_cmd
->cmd_action_1
)
return pldm_cmd
->cmd_action_1 (pldm_cmd
->ldm
->client_data
, argv
[1]);
//////////////////////////////////////////////////
int extra_cmd_action_2 (void*, int argc
, char **argv
)
LdmCmdNode
*pnode
= head_ldm_cmd
;
for (;pnode
; pnode
= pnode
->Next()) {
pldm_cmd
= pnode
->GetData ();
if (strcmp(argv
[0], pldm_cmd
->name
) == NULL
) {
if (pldm_cmd
->cmd_action_2
)
return pldm_cmd
->cmd_action_2 (pldm_cmd
->ldm
->client_data
, argc
, argv
);
//////////////////////////////////////////////////
//////////////////////////////////////////////////
extern int mmi_cmd_action (void*, int argc
, char **argv
) ;
UI_register_cmd_2 ((char*)"mod", help_string
, mod_cmd_action
, NULL
);
UI_register_cmd_2 ((char*)"mmi", mmi_help_string_1
, mmi_cmd_action
, NULL
);
UI_register_cmd_2 ((char*)"ldm", mmi_help_string_1
, mmi_cmd_action
, NULL
);
UI_register_cmd_2 ((char*)"ioa", mmi_help_string_1
, mmi_cmd_action
, NULL
);
UI_register_cmd_2 ((char*)"uldm",mmi_help_string_2
, mmi_cmd_action
, NULL
);
UI_register_cmd_2 ((char*)"cfg", mmi_help_string_4
, mmi_cmd_action
, NULL
);
UI_register_cmd_2 ((char*)"sysconf", mmi_help_string_4
, mmi_cmd_action
, NULL
);
UI_register_cmd_2 ((char*)"modinfo", mmi_help_string_5
, mmi_cmd_action
, NULL
);
//////////////////////////////////////////////////
//////////////////////////////////////////////////
//// TM API routines ////
//////////////////////////////////////////////////
//////////////////////////////////////////////////
void TM_enable_interval (uint64_t ti
)
tm_time_target
= ti
+ SYSTEM_get_ticks ();
void TM_disable_interval ()
tm_time_target
= 0xffffffffffffffffLLU
;
//////////////////////////////////////////////////
void TM_invalidate (tracemod_t
*pmod
)
//////////////////////////////////////////////////
static void delete_args(Ldm
*pldm
)
for (int i
= 0; i
< pldm
->argc
; i
++)
//////////////////////////////////////////////////
LdmNode
*pnode
, *prv
= NULL
;
for (pnode
=head_ldm
; pnode
!=NULL
; pnode
= pnode
->Next()) {
pldm
= pnode
->GetData ();
ui
->error("TM: invalidating module <%s>\n", pldm
->name
);
if (dlclose (pldm
->so_handle
))
ui
->error("TM: dlclose failed: %s\n", dlerror());
LdmNode::DeleteNode (&head_ldm
, prv
);
//////////////////////////////////////////////////
Ldm
* TM_find_mod_spec (char * name
)
for (pnode
=head_spec_ldm
; pnode
!=NULL
; pnode
=pnode
->Next()) {
pldm
= pnode
->GetData ();
if (strcmp(pldm
->name
, name
) == NULL
) {
//////////////////////////////////////////////////
Ldm
* TM_find_mod_spec_instance (tracemod_t
*parent
, char * name
)
for (pnode
=head_spec_ldm
; pnode
!=NULL
; pnode
=pnode
->Next()) {
pldm
= pnode
->GetData ();
if ((pldm
->parent
== parent
) && (!name
|| !strcmp(pldm
->name
, name
))) {
//////////////////////////////////////////////////
void TM_clean_mod_spec ()
LdmNode
*pnode
, *prv
= NULL
;
for (pnode
=head_spec_ldm
; pnode
!=NULL
; pnode
=pnode
->Next()) {
pldm
= pnode
->GetData ();
ui
->error("TM: invalidating module <%s>\n", pldm
->name
);
if (dlclose (pldm
->so_handle
))
ui
->error("TM: dlclose failed: %s\n", dlerror());
LdmNode::DeleteNode (&head_spec_ldm
, prv
);
//////////////////////////////////////////////////
bool_t
TM_verify (tracemod_t
*pmod
)
for (pnode
=head_ldm
; pnode
!=NULL
; pnode
=pnode
->Next()) {
pldm
= pnode
->GetData ();
for (pnode
=head_spec_ldm
; pnode
!=NULL
; pnode
=pnode
->Next()) {
pldm
= pnode
->GetData ();
//////////////////////////////////////////////////
tracemod_t
*TM_self_register (const char* mod_name
,
const char *help
, TM_OPAQUE_DATA client_data
)
for (pnode
=head_ldm
; pnode
!=NULL
; pnode
=pnode
->Next()) {
pldm
= pnode
->GetData ();
if (strcmp(mod_name
, pldm
->name
) == NULL
) {
pldm
->help
= (char*) help
;
pldm
->client_data
= client_data
;
ui
->error("TM : unable to find MODULE <%s> \n", mod_name
);
//////////////////////////////////////////////////
tracemod_t
*TM_self_register_spec (const char* mod_name
, TM_OPAQUE_DATA client_data
)
for (pnode
=head_spec_ldm
; pnode
!=NULL
; pnode
=pnode
->Next()) {
pldm
= pnode
->GetData ();
if (strcmp(mod_name
, pldm
->name
) == NULL
) {
pldm
->client_data
= client_data
;
ui
->error("TM : unable to find MODULE <%s> \n", mod_name
);
//////////////////////////////////////////////////
void TM_ui_register_1 (tracemod_t
* pmod
, const char* name
,
const char */
*shelp*/
, const char * lhelp
, fn_ui_1 fn
)
for (pnode
=head_ldm
; pnode
!=NULL
; pnode
=pnode
->Next()) {
pldm
= pnode
->GetData ();
if (pldm_cmd
= ldm_cmd_add (name
, fn
, NULL
)) {
UI_register_cmd_1 ((char*)name
, (char*)lhelp
, extra_cmd_action_1
, NULL
);
for (pnode
=head_spec_ldm
; pnode
!=NULL
; pnode
=pnode
->Next()) {
pldm
= pnode
->GetData ();
if (pldm_cmd
= ldm_cmd_add (name
, fn
, NULL
)) {
UI_register_cmd_1 ((char*)name
, (char*)lhelp
, extra_cmd_action_1
, NULL
);
ui
->error("TM: module <%s> not found\n", pldm
->name
);
//////////////////////////////////////////////////
void TM_ui_register_2 (tracemod_t
* pmod
, const char* name
,
const char */
*shelp*/
, const char * lhelp
, fn_ui_2 fn
)
for (pnode
=head_ldm
; pnode
!=NULL
; pnode
=pnode
->Next()) {
pldm
= pnode
->GetData ();
if (pldm_cmd
= ldm_cmd_add (name
, NULL
, fn
)) {
UI_register_cmd_2 ((char*)name
, (char*)lhelp
, extra_cmd_action_2
, NULL
);
for (pnode
=head_spec_ldm
; pnode
!=NULL
; pnode
=pnode
->Next()) {
pldm
= pnode
->GetData ();
if (pldm_cmd
= ldm_cmd_add (name
, NULL
, fn
)) {
UI_register_cmd_2 ((char*)name
, (char*)lhelp
, extra_cmd_action_2
, NULL
);
ui
->error("TM: module <%s> not found\n", pldm
->name
);
//////////////////////////////////////////////////
void TM_time_interval_register (tracemod_t
*pmod
, fn_time_interval fn
)
//////////////////////////////////////////////////
void TM_ui_unregister (tracemod_t
* /*pmod*/, const char *name
)
LdmCmdNode
*pnode
= head_ldm_cmd
, *prv
= NULL
;
for (;pnode
; pnode
= pnode
->Next()) {
pldm_cmd
= pnode
->GetData();
if (strcmp(name
, pldm_cmd
->name
) == NULL
) {
LdmCmdNode::DeleteHead (&pnode
);
UI_invalidate_cmd ((char*)name
);
LdmCmdNode::DeleteNode ((LdmCmdNode
**)&head_ldm_cmd
, prv
);
UI_invalidate_cmd ((char*)name
);
//////////////////////////////////////////////////
void TM_set_type_ext (tracemod_t
*pmod
, Byte type
)
(type
!= TM_TYPE_EXT_CPU
) &&
(type
!= TM_TYPE_EXT_DEVICE
) &&
(type
!= TM_TYPE_EXT_SIM
)
ui
->error("TM : TM_set_type_ext (unknown type = 0x%x) \n", type
);
//////////////////////////////////////////////////
void TM_cpustate_register (tracemod_t
* pmod
, fn_cpustat fn
)
pmod
->cpustat_action
= fn
;
void TM_cpustate_registerB (tracemod_t
* pmod
, fn_cpustatB fn
)
pmod
->cpustat_actionB
= fn
;
void TM_set_mode (tracemod_t
*pmod
, Byte mode
)
for (pnode
=head_ldm
; pnode
!=NULL
; pnode
=pnode
->Next()) {
pldm
= pnode
->GetData ();
if (!(pldm
->mode
& TM_MT_SAFE
)) {