Initial commit of OpenSPARC T2 architecture model.
[OpenSPARC-T2-SAM] / sam-t2 / sam / system / tracemod / tm_mmi.cc
// ========== Copyright Header Begin ==========================================
//
// OpenSPARC T2 Processor File: tm_mmi.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.
* All rights reserved.
*/
#pragma ident "@(#)1.4 01/11/06 tm_mmi.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
* Supplement
*/
//
//
#include <sys/types.h>
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <synch.h>
#include <dlfcn.h>
#include <ctype.h>
#include <limits.h>
#include "types.h"
#include "blaze_globals.h"
#include "ui.h"
//#include "cpu.h"
#include "cpu_interface.h"
#include "vtracer.h"
#include "vtracer_async_queue.h"
#include "system.h"
#include "dr.h"
typedef void* TM_OPAQUE_DATA;
#include "tracemod.h"
#include "mmi.h"
#include "mmi-blaze.h"
#include "tm_impl.h"
#include "dev_props.h"
void ldm_delete_head_spec ();
volatile bool config_is_done;
int bdt_verbose = 0;
/////////////////////////////////////////////////////////////
MmiVarNode *pMmiVarList = NULL;
mmi_dr_s * mmi_dr_list = NULL;
int mmi_dr_list_sz = 0;
int mmi_dr_list_count = 0;
struct property_list *plist = NULL;
uint64_t fkprom_dtinbuf_pa = 0x50;
int fkprom_dtinbuf_offset = 0; // offset at which to write device property data
/////////////////////////////////////////////////////////////
mmi_bool_t mmi_register_instance_creator (const char * modname, mmi_instance_creator fn)
{
// In order to register an instance creator, add the module's name
// into the module list to show it is here.
// ldm_add_spec ((char *)modname, 0); // for module dependency
tracemod_t *tm = TM_self_register_spec (modname, NULL);
struct ldm_t *pldm;
if (tm == NULL) {
return mmi_false;
}
pldm = (struct ldm_t *) tm;
TM_set_mode (tm, TM_EXT_IO);
TM_set_type_ext (tm, TM_TYPE_EXT_DEVICE);
pldm->create_instance = fn;
return mmi_true;
} // mmi_register_instance_creator
/////////////////////////////////////////////////////////////
mmi_bool_t mmi_unregister_instance_creator (mmi_instance_t mod)
{
Ldm* pldm = (Ldm *)mod;
if (!TM_verify (pldm)) {
return mmi_false;
}
TM_invalidate (pldm);
TM_clean_mod_spec();
TM_clean_mod();
return mmi_true;
}
/////////////////////////////////////////////////////////////
int mmi_register_cb_data (module_t *mod, void *cb_data)
{
Ldm* pldm = (Ldm *)mod;
if (!TM_verify (pldm)) {
return (-1);
}
TM_register_client_data(pldm, cb_data);
return 0;
}
mmi_bool_t mmi_register_asi_cb_data (mmi_instance_t instance, void *cb_data)
{
Ldm* pldm = (Ldm *)instance;
if (!TM_verify (pldm)) {
return mmi_false;
}
TM_register_asi_client_data (pldm, cb_data);
return mmi_true;
}
/////////////////////////////////////////////////////////////
void* mmi_get_cb_data (module_t *mod)
{
return mod->client_data;
}
void* mmi_get_asi_cb_data (module_t *mod)
{
return mod->asi_client_data;
}
/////////////////////////////////////////////////////////////
void* mmi_register_cb_cycle (mmi_instance_t instance, mmi_event_cycle handler, uint64_t repeat)
{
void *cb_data = TM_get_client_data(instance);
return TM_register_time_intf ((Ldm*)instance, cb_data, handler, repeat);
}
/////////////////////////////////////////////////////////////
void mmi_unregister_cb_cycle (mmi_instance_t mod, void * intf)
{
TM_unregister_time_intf ((Ldm*)mod, intf);
}
/////////////////////////////////////////////////////////////
int mmi_disable_cb_cycle (void * intf)
{
TM_disable_time_intf (intf);
return 0;
}
/////////////////////////////////////////////////////////////
int mmi_enable_cb_cycle (void * intf, blaze_cycle_t repeat )
{
TM_enable_time_intf (intf, repeat);
return 0;
}
/////////////////////////////////////////////////////////////
/* MMI UI command interface */
void mmi_register_module_cmd(mmi_module_t mod, const char * helpstring, mmi_module_cmd_fn fn)
{
Ldm * pldm = (Ldm *)mod;
char * modname = strdup(pldm->name);
TM_ui_register_2(pldm, modname, helpstring, helpstring, fn);
} // void mmi_register_module_cmd(mmi_module_t mod, const char * helpstring, mmi_module_cmd_fn fn)
void mmi_register_instance_cmd(mmi_instance_t instance, const char * helpstring, mmi_instance_cmd_fn fn)
{
Ldm * pldm = (Ldm *) instance;
char * instancename = strdup(pldm->name);
TM_ui_register_2(pldm, instancename, helpstring, helpstring, fn);
} // void mmi_register_instance_cmd(mmi_instance_t instance, const char * helpstring, mmi_instance_cmd_fn fn)
/////////////////////////////////////////////////////////////
extern bool_t add_asi_module (tracemod_t* mod, uint32_t asi, mmi_ld_asi_action ld_handler,
mmi_st_asi_action st_handler);
/////////////////////////////////////////////////////////////
void
mmi_register_asi_action (mmi_instance_t instance, uint32_t asi,
mmi_ld_asi_action ld_handler, mmi_st_asi_action st_handler)
{
AsiHandlerNode *pnode = AsiHandlerNode::CreateInstance("ASI handler list");
AsiHandlerT *ph;
struct ldm_t *pldm = (struct ldm_t *)instance;
if (pnode == NULL) {
ui->error("MMI: Unable to create ASI interceptor for ASI = 0x%x\n", asi);
return;
}
ph = pnode->GetData ();
ph->asi = asi;
ph->vaddr = 0;
ph->mmi_ld_action = ld_handler;
ph->mmi_st_action = st_handler;
if (add_asi_module(pldm, asi, ld_handler, st_handler)) {
AsiHandlerNode::AddHead ((AsiHandlerNode**)&pldm->headAsi, pnode);
} else {
ui->error("MMI: unable to register ASI interceptor\n");
}
}
/////////////////////////////////////////////////////////////
int mmi_argc(mmi_instance_t instance)
{
return ((module_t *)instance)->argc;
}
char *mmi_argv(mmi_instance_t instance, int index)
{
module_t * mod = (module_t *) instance;
if (index < 0 || mod->argc <= index)
return NULL;
return mod->argv[index];
}
/////////////////////////////////////////////////////////////
void set_module_args(Ldm *pldm, int argc, char **argv)
{
int i;
if (pldm->argv) {
for (i = 0; i < pldm->argc; i++)
free(pldm->argv[i]);
free(pldm->argv);
}
pldm->argc = argc;
pldm->argv = (char**) calloc (argc, sizeof(char*));
for (i = 0; i < argc; i++)
pldm->argv[i] = (char*)strdup(argv[i]);
}
/////////////////////////////////////////////////////////////
static Ldm *load_module(char *modname, char * pathp, char *soname)
{
Ldm *pldm = NULL;
pldm = ldm_add_spec (modname, soname);
if (pldm == NULL) {
return NULL;
}
pldm->so_handle = mod_dlopen (pathp, soname, RTLD_LAZY|RTLD_GLOBAL|RTLD_PARENT);
if (pldm->so_handle == NULL) {
ldm_delete_head_spec();
return NULL;
}
if (!pldm->valid) {
TM_clean_mod_spec ();
return NULL;
}
return pldm;
}
/////////////////////////////////////////////////////////////
int ldm_cmd_action(int argc, char **argv)
{
Ldm *pldm = NULL;
// ldm <modname> <instance> [<XX.so>]
if (argc == 4) {
pldm = load_module(argv[1], NULL, argv[3]);
if (pldm) {
set_module_args(pldm, argc, argv);
if (pldm->create_instance) {
pldm->create_instance (argv[1], argv[2]);
}
else {
ui->error("LDM: MMI device module - instance creator not found !! \n");
return 0;
}
}
}
else if (argc == 3) {
// ldm <modname> <instance>
Ldm *pmod = TM_find_mod_spec (argv[1]);
if (pmod == NULL) {
ui->error("LDM: MMI device module <%s> not found \n", argv[1]);
return 0;
}
if (pmod->create_instance) {
pmod->create_instance (argv[1], argv[2]);
}
else {
ui->error("LDM: MMI device module - instance creator not found !! \n");
return 0;
}
}
return 1;
}
/////////////////////////////////////////////////////////////
int sysconf_usage(const char *msg)
{
ui->error("sysconf: %s\n", msg);
ui->error("usage: sysconf [-p <modpath> ] <modname> [ <instance_name> [ args... ] ]\n");
return -1;
}
/////////////////////////////////////////////////////////////
extern Vcpu * init_cpu ( char *path, int argc, char **argv );
int sysconf_cmd_action(int argc, char **argv)
{
Ldm *pldm = NULL;
char modname[64], libname[1024];
static char path[512] = {"."};
/* arg to load_module, if null the searchlist */
/* with $ORIGIN in it is used, if not this explicit path is used */
char * pathp = NULL;
// sysconf [-p <modpath> ] <modname> [ <instance_name> [ args... ] ]
if (argc < 2)
return sysconf_usage("missing args");
if (strcmp (argv[1], "-p") == 0) {
if (argc == 2)
return sysconf_usage("missing args");
if (argc == 3) {
mod_addpath (argv[2]); /* add to generic search path */
return 1;
}
/* otherwise, this is a module specific path prefix, handle below */
}
// XXX should remove it completely
if ( (strcmp(argv[1], "done") == 0) && (argc == 2) ) {
// complete_initialization();
return 1;
}
if ( strcmp ( argv[1], "cpu" ) == 0 )
{
// cpu module
// create a new cpu instance;
// keep a pointer in a global array;
// skip first two args: "sysconf" and "cpu";
// we really do only pass pathp here,
// the fname is derived from the cpu-type attribute
Vcpu *vcpu = init_cpu (pathp, argc-2, argv+2);
// configure cpu params in fakeprom;
VCPU_Config &config_info = vcpu->config;
#ifdef V5_FAKEPROM
// cpu clock frequency
memwrite64s_nl(mm1, 0x20, config_info.cpufreq);
// system clock frequency
memwrite64s_nl(mm1, 0x28, the_arch.stick_freq);
// number of cpu's
memwrite32u_nl(mm1, 0x14, g_nvcpu);
#endif
// keep a global copy
// TODO: the_arch maybe soon obsolete
the_arch.cpu_freq = config_info.cpufreq;
// read stickfreq from conf suplied value
config_info.stickfreq = the_arch.stick_freq;
the_arch.numcpus = g_nvcpu;
return 1;
}
for (int i = 1; i < argc; i++) {
if (strcmp(argv[i], "-p") == 0) {
if (++i >= argc)
return sysconf_usage("missing -p <modpath>");
strlcpy(path, argv[i], sizeof path);
pathp = &path[0]; /* override the searchlist */
}
else if (argv[i][0] == '-') {
return sysconf_usage(argv[i]);
}
else if (!pldm) {
strlcpy(modname, argv[i], sizeof modname);
sprintf (libname, "%s.so", modname);
pldm = TM_find_mod_spec(modname);
if (!pldm)
pldm = load_module (modname, pathp, libname);
assert(pldm != NULL);
if (!pldm)
return sysconf_usage("can't load the module");
}
else {
if (TM_find_mod_spec(argv[i]))
return sysconf_usage("module instance already exists");
mmi_instance_t ins = mmi_register_instance (modname, argv[i], NULL, argv[i]);
if (!ins)
return sysconf_usage("failed to create module instance");
set_module_args((module_t *)ins, argc-(i+1), &argv[i+1]);
if (pldm->create_instance) {
pldm->create_instance (modname, argv[i]);
}
return 0;
}
}
return 1;
}
/////////////////////////////////////////////////////////////
void modinfo_list_modules()
{
Ldm *pldm;
LdmNode *pnode;
for (pnode=head_spec_ldm; pnode!=NULL; pnode = pnode->Next()) {
pldm = pnode->GetData ();
if (!pldm->parent)
ui->output("<%s>\n", pldm->name);
}
for (pnode=head_spec_ldm; pnode!=NULL; pnode=pnode->Next()) {
pldm = pnode->GetData ();
if (pldm->parent)
ui->output("<%s> parent=<%s>\n", pldm->name, pldm->parent->name);
}
}
void modinfo_print_info(char *name)
{
Ldm *pldm;
LdmNode *pnode;
if (!name)
return;
for (pnode=head_spec_ldm; pnode!=NULL; pnode=pnode->Next()) {
pldm = pnode->GetData ();
if (!strcmp(pldm->name, name)) {
if (pldm->modinfo_cb)
pldm->modinfo_cb(pldm->client_data);
return;
}
}
ui->error("%s is not loaded\n", name);
}
int modinfo_cmd_action(int argc, char **argv)
{
if (argc < 2) {
/* modinfo_list_modules();
}
else if (!strcmp(argv[1], "all") && argc == 2) { */
Ldm *pldm;
LdmNode *pnode;
for (pnode=head_spec_ldm; pnode!=NULL; pnode=pnode->Next()) {
pldm = pnode->GetData ();
if (pldm->help)
ui->output("%s: %s\n", pldm->name, pldm->help);
if (pldm->modinfo_cb)
pldm->modinfo_cb(pldm->client_data);
}
}
else {
for (int i = 1; i < argc; i++)
modinfo_print_info(argv[i]);
}
return 0;
}
/////////////////////////////////////////////////////////////
int mmi_cmd_action (void*, int argc, char **argv)
{
if (SYSTEM_is_running ()) {
ui->error("mmi_cmd_action(%s) called while in run state!!!\n", argv[0]);
}
if (strcmp (argv[0], "uldm") == NULL) {
ui->error("uldm has been deprecated. config specifications are not UI commands\n");
}
else if (strcmp (argv[0], "ioa") == NULL) {
if (argc < 4) {
ui->error("UI:usage : ioa <instance name> <ADDR1> <ADDR2>\n");
return 0;
}
uint64_t baddr, eaddr;
sscanf (argv[2], "%lli", &baddr);
sscanf (argv[3], "%lli", &eaddr);
assert(0);
return false;
}
else if (strcmp(argv[0], "ldm") == NULL) {
return ldm_cmd_action(argc, argv);
}
else if (!strcmp(argv[0], "cfg") || !strcmp(argv[0], "sysconf")) {
return sysconf_cmd_action(argc, argv);
}
else if (!strcmp(argv[0], "modinfo")) {
return modinfo_cmd_action(argc, argv);
}
return 1;
}
/////////////////////////////////////////////////////////////
mmi_instance_t mmi_register_instance (const char * modname, const char *instance_name, void * instance_data, const char * help)
{
// parent module must exist
Ldm *pmod = TM_find_mod_spec ((char*)modname);
if (pmod == NULL) {
ui->error("MMI: module <%s> not found \n", modname);
return NULL;
}
// create instance, unless already done
Ldm *pseudo_mod = TM_find_mod_spec_instance(pmod, (char*)instance_name);
if (pseudo_mod) {
pseudo_mod->help = strdup(help);
}
else {
pseudo_mod = TM_self_pseudomod_spec (pmod, (char*)instance_name, help, NULL);
if (pseudo_mod) {
TM_set_mode (pseudo_mod, TM_EXT_IO);
TM_set_type_ext (pseudo_mod, TM_TYPE_EXT_DEVICE);
}
}
mmi_register_cb_data(pseudo_mod, instance_data);
return (mmi_instance_t) pseudo_mod;
} // mmi_register_instance()
void * mmi_get_instance_data(mmi_instance_t instance)
{
return mmi_get_cb_data((module_t *) instance);
}
/////////////////////////////////////////////////////////////
void TM_module_init()
{
Ldm *pldm;
LdmNode *pnode;
for (pnode=head_spec_ldm; pnode!=NULL; pnode=pnode->Next()) {
pldm = pnode->GetData ();
if (pldm->config_cb)
(pldm->config_cb)(pldm->client_data, pldm, pldm->name, MMI_CONFIG_INIT_DONE);
}
// register the atexit function
atexit(TM_run_atexit_cb);
config_is_done = true;
}
/////////////////////////////////////////////////////////////
// call the config_cb callback of each registered module with
// the event MMI_CONFIG_DELETE_MODULE. The modules checks to see
// if the deleted module is itself, in which case it calls delete
// on itself
void TM_run_atexit_cb(){
Ldm *pldm;
LdmNode *pnode;
for (pnode=head_spec_ldm; pnode!=NULL; pnode=pnode->Next()) {
pldm = pnode->GetData ();
if (pldm->config_cb)
(pldm->config_cb)(pldm->client_data, pldm, pldm->name, MMI_CONFIG_DELETE_MODULE);
}
}
/////////////////////////////////////////////////////////////
void TM_run_config_cb (tracemod_t *mod, int ev)
{
Ldm *pldm;
LdmNode *pnode;
// tell other mods first
for (pnode=head_spec_ldm; pnode!=NULL; pnode=pnode->Next()) {
pldm = pnode->GetData ();
if (pldm->config_cb && pldm != mod)
(pldm->config_cb)(pldm->client_data, mod, mod->name, (mmi_config_t)ev);
}
// run this mod last, in case it is going away
if (mod->config_cb)
(mod->config_cb)(mod->client_data, mod, mod->name, (mmi_config_t)ev);
}
/////////////////////////////////////////////////////////////
int mmi_unregister_module (module_t *mod)
{
Ldm* pldm = (Ldm *)mod;
if (!TM_verify (pldm)) {
return (-1);
}
// clean out timer callbacks
TM_unregister_time_intf(pldm, NULL);
if (pldm->so_handle) { // delete instances first
Ldm* instance;
while ((instance = TM_find_mod_spec_instance(pldm, NULL)) != NULL)
mmi_unregister_module(instance);
}
TM_run_config_cb (mod, MMI_CONFIG_DELETE_MODULE);
TM_invalidate (pldm);
TM_clean_mod_spec();
TM_clean_mod();
return 0;
}
/////////////////////////////////////////////////////////////
module_t *mmi_get_instance_pointer (const char *modname, const char *instance_name)
{
Ldm * pldm = TM_find_mod_spec ((char*)modname);
if (instance_name == NULL) {
return (module_t*)pldm;
}
if (pldm == NULL)
return NULL;
pldm = TM_find_mod_spec_instance (pldm, (char*)instance_name);
return (module_t*)pldm;
}
/////////////////////////////////////////////////////////////
module_t *mmi_get_module (const char *modname)
{
char * s = strdup(modname);
module_t * module = TM_find_mod_spec(s);
free(s);
return module;
}
mmi_instance_t mmi_get_instance(const char * instancename)
{
char * s = strdup(instancename);
mmi_instance_t instance = TM_find_mod_spec(s);
free(s);
return instance;
}
/////////////////////////////////////////////////////////////
mmi_bool_t mmi_register_interface_cb (mmi_instance_t instance, mmi_interface_cb fn)
{
module_t * mod = (module_t *) instance;
if (!TM_verify (mod))
return mmi_false;
mod->interface_cb = fn;
return mmi_true;
}
/////////////////////////////////////////////////////////////
mmi_bool_t mmi_register_modinfo_cb (mmi_instance_t instance, mmi_modinfo_cb fn)
{
module_t * mod = (module_t *) instance;
if (!TM_verify (mod))
return mmi_false;
mod->modinfo_cb = fn;
return mmi_true;
}
/////////////////////////////////////////////////////////////
mmi_bool_t
mmi_register_config_cb (mmi_instance_t instance, mmi_config_cb fn)
{
module_t *mod = (module_t *) instance;
if (!TM_verify (mod))
return mmi_false;
mod->config_cb = fn;
// report the modules that exist
{
Ldm *pldm;
LdmNode *pnode;
for (pnode=head_spec_ldm; pnode!=NULL; pnode=pnode->Next()) {
pldm = pnode->GetData ();
fn(mod->client_data, pldm, pldm->name, MMI_CONFIG_NEW_MODULE);
}
}
// report this module to the others that exist
TM_run_config_cb(mod, MMI_CONFIG_NEW_MODULE);
return mmi_true;
}
/////////////////////////////////////////////////////////////
void *
mmi_get_interface (mmi_instance_t instance, const char *name)
{
module_t *mod = (module_t *) instance;
if (!TM_verify (mod))
return NULL;
if (mod->interface_cb)
return mod->interface_cb(mod->client_data, name);
if (mod->parent && mod->parent->interface_cb)
return mod->parent->interface_cb(mod->client_data, name);
return NULL;
}
/////////////////////////////////////////////////////////////
void mmi_memread(uint64_t paddr, uint8_t * data, uint64_t size,SAM_DeviceId sam_id)
{
assert((size>>32) == 0); // FIXME: need to fix this in Memory::block_read(). 2007.10.23
mm1->block_read(paddr,data,(int)size);
TRACE_DMA(/*is_write?*/ 0, size, paddr, sam_id);
} // void mmi_memread(uint64_t paddr, uint8_t * data, uint64_t size, SAM_DeviceId sam_id)
/////////////////////////////////////////////////////////////
void mmi_memwrite(uint64_t paddr, const uint8_t * data, uint64_t size,SAM_DeviceId sam_id)
{
assert((size>>32) == 0); // FIXME: need to fix this in Memory::block_write(). 2007.10.23
mm1->block_write(paddr,data,(int)size);
TRACE_DMA(/*is_write?*/ 1, size, paddr, sam_id);
} // void mmi_memwrite(uint64_t paddr, const uint8_t * data, uint64_t size, SAM_DeviceId sam_id)
/////////////////////////////////////////////////////////////
void mmi_register_start_stop(mmi_start_stop_cb start_action, mmi_start_stop_cb stop_action, void * userdata)
{
SYSTEM_ss_register((ss_action)stop_action, (ss_action) start_action, userdata);
} // void mmi_register_start_stop(mmi_start_stop_cb start_action, mmi_start_stop_cb stop_action, void * userdata)
/////////////////////////////////////////////////////////////
bool_t tm_mmi_dump(DR_OPAQUE drh) {
int i; char file_name[PATH_MAX];
for (i=0; i<mmi_dr_list_count; i++) {
ui->output("Dumping <%s> ...\n", mmi_dr_list[i].name);
snprintf(file_name, PATH_MAX, "%s/%s.dmp", DR_get_dir(), mmi_dr_list[i].name);
if (! mmi_dr_list[i].dump_fn(mmi_dr_list[i].userdata, file_name)) {
ui->error("dump failed\n");
return FALSE;
}
ui->output("done\n");
}
return TRUE;
} // mmi_dump()
/////////////////////////////////////////////////////////////
bool_t tm_mmi_restore(DR_OPAQUE drh) {
int i; char file_name[PATH_MAX];
for (i=0; i<mmi_dr_list_count; i++) {
ui->output("Restoring <%s> ...", mmi_dr_list[i].name);
snprintf(file_name, PATH_MAX, "%s/%s.dmp", DR_get_rdir(drh), mmi_dr_list[i].name);
if (!mmi_dr_list[i].restore_fn(mmi_dr_list[i].userdata, file_name)) {
ui->error("restore failed\n");
return FALSE;
}
ui->output("done\n");
}
return TRUE;
} // mmi_restore()
/////////////////////////////////////////////////////////////
mmi_bool_t mmi_register_dump_restore(const char *name, mmi_dump_cb dump_fn, mmi_restore_cb restore_fn, void *userdata)
{
if (mmi_dr_list == NULL) {
mmi_dr_list_sz = 32;
mmi_dr_list = new mmi_dr_s [mmi_dr_list_sz];
mmi_dr_list_count = 0;
DR_register("MMI:DR", tm_mmi_dump, tm_mmi_restore, NULL);
}
if (mmi_dr_list_count == mmi_dr_list_sz) {
int newsz = 2*mmi_dr_list_sz;
mmi_dr_s * newlist = new mmi_dr_s[newsz];
size_t nbytes = mmi_dr_list_sz*sizeof(mmi_dr_s);
memcpy(newlist, mmi_dr_list, nbytes);
memset(newlist + mmi_dr_list_sz, 0, nbytes);
delete [] mmi_dr_list;
mmi_dr_list = newlist;
mmi_dr_list_sz = newsz;
}
mmi_dr_list[mmi_dr_list_count].userdata = userdata;
mmi_dr_list[mmi_dr_list_count].name = strdup(name);
mmi_dr_list[mmi_dr_list_count].dump_fn = dump_fn;
mmi_dr_list[mmi_dr_list_count].restore_fn = restore_fn;
mmi_dr_list_count++;
return mmi_true;
} // mmi_bool_t mmi_register_dump_restore(void * userdata, mmi_dump_cb dump_fn, mmi_restore_cb restore_fn)
/////////////////////////////////////////////////////////////
int64_t mmi_get_time() // simulated microseconds, since boot
{
return SYSTEM_get_time(TW_CURRENT);
}
// event-queue based internal synchonization
mmi_bool_t mmi_register_event (int64_t when,
mmi_event_cb event_fn, void * userdata1, void * userdata2)
{
SYSTEM_register_event (when, (EventFunc_T*)event_fn, userdata1, userdata2,
(UnloadFunc_T*)NULL, "mmi-unknown");
return mmi_true;
}
/////////////////////////////////////////////////////////////
int mmi_register_cb_instr (module_t *mod, fn_event_cpu handler)
{
ui->error("SAM MMI: mmi_register_cb_instr no longer supported (called from module %s)\n", mod->name);
return -1;
}
/////////////////////////////////////////////////////////////
int mmi_register_cb_memop (module_t *mod, fn_event_cpu handler)
{
ui->error("SAM MMI: mmi_register_cb_memop no longer supported (called from module %s)\n", mod->name);
return -1;
}
/////////////////////////////////////////////////////////////
int mmi_register_cb_trap (module_t *mod, fn_event_cpu handler)
{
ui->error("SAM MMI: mmi_register_cb_trap no longer supported (called from module %s)\n", mod->name);
return -1;
}
/////////////////////////////////////////////////////////////
int mmi_register_cb_trapexit (module_t *mod, fn_event_cpu handler)
{
ui->error("SAM MMI: mmi_register_cb_trapexit no longer supported (called from module %s)\n", mod->name);
return -1;
}
/////////////////////////////////////////////////////////////
int mmi_register_cb_tlb (module_t *mod, fn_event_cpu handler)
{
ui->error("SAM MMI: mmi_register_cb_tlb no longer supported (called from module %s)\n", mod->name);
return -1;
}
/////////////////////////////////////////////////////////////
int mmi_register_cb_cpustate (module_t *mod, fn_event_cpu handler)
{
ui->error("SAM MMI: mmi_register_cb_cpustate no longer supported (called from module %s)\n", mod->name);
return -1;
}
/////////////////////////////////////////////////////////////
int mmi_register_cb_dma (module_t *mod, fn_event_dma handler)
{
ui->error("SAM MMI: mmi_register_cb_dma no longer supported (called from module %s)\n", mod->name);
return -1;
}
/////////////////////////////////////////////////////////////
int mmi_set_cb_mask (module_t *mod, uint32_t mask)
{
ui->error("SAM MMI: mmi_set_cb_mask no longer supported (called from module %s)\n", mod->name);
return -1;
}
/////////////////////////////////////////////////////////////
/*OBSOLETE*/
int mmi_register_io_action (module_t *mod, mmi_io_action ld_handler, mmi_io_action st_handler)
{
if ((mod == 0) || (ld_handler == 0) || (st_handler == 0))
return (-1);
TM_register_io_mmi_action ((tracemod_t*)mod, (fn_misc)ld_handler, (fn_misc)st_handler);
return 0;
}
/////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////
mem_t* mmi_get_memobj (cpu_t *)
{
return mm1; //memobj ();
}
/////////////////////////////////////////////////////////////
//
// TODO : Might be a subject of MODULE REDIRECTION itself
//
int mmi_iommu_va2pa (module_t *, int is_read, uint64_t va, uint64_t *)
{
uint64_t local_pa;
assert(0);
return local_pa ? 0 : (-1);
}
/////////////////////////////////////////////////////////////
//
// review of Sun4u Mondo interrupts:
// sender receiver
// ------ --------
//
// cpu-to-cpu:
// data => IDDR
// (tgt_AgentID<<14) => IDCR--->---IRSR => bits-<5:0> = src_AgentID
// IRDR => data
// schizo-to-cpu:
// (tgt_AgentID<<26 | src_AgentID<<6 | dev_INO) =>...
// ...=> INR--->---IRSR => bits-<5:0> = src_AgentID
// (*) IRDR => bits-<10:0> = (AID<<6) | INO
// *
// *-> idata[0] must be supplied by schizo HW _!!!_
//
int mmi_interrupt_packet (int dst_aid, int src_aid, uint64_t *idata)
{
intrT intr; // recently typedef'ed to "cpu_lib_intf.h"/InterruptRequest
intr.isid = src_aid;
intr.itid = dst_aid;
intr.data[0] = idata[0];
intr.data[1] = idata[1];
intr.data[2] = idata[2]; // data[3..7] not part of original mondo spec
// and never referenced by solaris :-!.
SYSTEM_interrupt_by_sid (dst_aid, src_aid, &intr);
return 0;
}
/////////////////////////////////////////////////////////////
//
// Sun4v ??? interrupt
//
int mmi_interrupt_vector (int dest_cpuid, void *src, int src_iscpu, uint32_t vnum, int traptype)
{
intrT intr;
intr.isid = 0xF00 | traptype; // Patch - to distinguish between
intr.itid = dest_cpuid;
intr.data[0] = vnum;
SYSTEM_interrupt_by_sid (dest_cpuid, 0, &intr);
return 0;
}
/////////////////////////////////////////////////////////////
int mmi_reset (cpu_t *, void *, resettype_t )
{
ui->error("MMI: RESET is not implemented yet \n");
return (-1);
}
/////////////////////////////////////////////////////////////
int mmi_get_ncpu ()
{
return SYSTEM_get_ncpu ();
}
int mmi_get_cpu_sid (cpu_t *sp)
{
return sp->id();
}
cpu_t *mmi_get_cpuptr_by_sid (int id)
{
return get_vcpu(id);
}
uint64_t mmi_get_cpufreq ()
{
return SYSTEM_get_cpufreq();
}
char *mmi_get_comment_string (void *, objtype_t )
{
return (char*)strdup("unimplemented");
}
int mmi_complete_delayed_load (cpu_t *, uint64_t )
{
ui->error("MMI: complete delayed load is not implemented yet \n");
return -1;
}
int mmi_delay_execution (cpu_t *sp, blaze_cycle_t delay)
{
SYSTEM_cycle_delay (sp->id(), (uint32_t)delay);
return 0;
}
//////////////////////////////////////////////////
int mmi_register_ui_variable (module_t *module, const char *varname,
vartype_t vartype, void *varptr, int writable, fn_setvar writer)
{
MmiVar *pvar;
MmiVarNode *pnode = MmiVarNode::CreateInstance ("MMI Varlist");
if (pnode == NULL) {
ui->error("MMI:Unable to register UI VARIABLE <%s>\n", varname);
return -1;
}
if (module == 0) {
return -1;
}
switch (vartype) {
case VAR_INT:
case VAR_LONG_INT:
case VAR_STRING:
case VAR_BOOL:
break;
default :
ui->error("MMI: Uknown variable type <%d> \n", vartype);
return -1;
}
pvar = pnode->GetData ();
pvar->name = (const char*)strdup(varname);
pvar->vtype = vartype;
pvar->writable = writable;
pvar->action = writer;
pvar->module = module;
pvar->varptr = varptr;
MmiVarNode::AddHead (&pMmiVarList, pnode);
return 0;
}
//////////////////////////////////////////////////
int mmi_set_ui_variable (module_t *module, const char *varname, void *val)
{
MmiVar *pvar;
MmiVarNode *pnode = pMmiVarList;
char **pq;
for (;pnode; pnode = pnode->Next()) {
pvar = pnode->GetData ();
if (strcmp (varname, pvar->name) == NULL) {
if (module == pvar->module) {
if (pvar->writable && pvar->action) {
void *cb_data = TM_get_client_data ((void *)module);
pvar->action(cb_data, val);
return 0;
}
else if (pvar->writable) {
switch (pvar->vtype) {
case VAR_INT:
*((uint32_t*) pvar->varptr) = *( (uint32_t*) val);
break;
case VAR_LONG_INT:
*((uint64_t*) pvar->varptr) = *( (uint64_t*) val);
break;
case VAR_STRING:
pq = (char**)&(pvar->varptr);
*pq = (char*)strdup((char*)val);
break;
case VAR_BOOL:
*((uint8_t*) pvar->varptr) = *( (uint8_t*) val);
break;
default :
return -1;
}
return 0;
}
}
}
}
return -1;
}
//////////////////////////////////////////////////
/////////////////////////////////
// FlexConfig-related additions
/////////////////////////////////
char *ldm_get_instanceof(char *modname) {
Ldm* pldm;
LdmNode *pnode = head_spec_ldm;
while(pnode) {
pldm = pnode->GetData();
if ( strstr(pldm->name, modname) )
return pldm->name;
pnode = pnode->Next();
}
return NULL;
}