From c56648379cde6ea3bcfac07923bb560734c6e16f Mon Sep 17 00:00:00 2001 From: dgilbert Date: Thu, 28 Jul 2011 16:42:28 -0500 Subject: Virtual File System module load and unload Change-Id: Iaa6a256a8a15ac48bfba5bc1cab292c5ac246166 Reviewed-on: http://gfw160.austin.ibm.com:8080/gerrit/253 Tested-by: Jenkins Server Reviewed-by: A. Patrick Williams III Reviewed-by: Daniel M. Crowell --- src/usr/cxxtest/cxxtestexec.C | 2 + src/usr/initservice/baseinitsvc/initservice.C | 104 +++++--- src/usr/initservice/baseinitsvc/initsvctasks.H | 21 +- src/usr/initservice/common/initsvcstructs.H | 12 +- src/usr/initservice/extinitsvc/extinitsvc.C | 21 +- src/usr/initservice/extinitsvc/extinitsvctasks.H | 7 +- src/usr/makefile | 4 +- src/usr/vfs/makefile | 8 + src/usr/vfs/vfsrp.C | 317 +++++++++++++++++++++++ src/usr/vfs/vfsrp.H | 90 +++++++ 10 files changed, 530 insertions(+), 56 deletions(-) create mode 100644 src/usr/vfs/makefile create mode 100644 src/usr/vfs/vfsrp.C create mode 100644 src/usr/vfs/vfsrp.H (limited to 'src/usr') diff --git a/src/usr/cxxtest/cxxtestexec.C b/src/usr/cxxtest/cxxtestexec.C index 5470b718a..645858c95 100644 --- a/src/usr/cxxtest/cxxtestexec.C +++ b/src/usr/cxxtest/cxxtestexec.C @@ -56,6 +56,8 @@ TRAC_INIT(&g_trac_cxxtest, "CXXTEST", 1024 ); extern "C" void _start(void *io_pArgs) { + // TODO These modules will eventually all be in the extended binary. + // VfsSystemModule* vfsItr = (VfsSystemModule*) VFS_EXTENDED_MODULE_TABLE_ADDRESS; VfsSystemModule* vfsItr = &VFS_MODULES[0]; tid_t tidrc = 0; uint64_t totalmodules = 0; diff --git a/src/usr/initservice/baseinitsvc/initservice.C b/src/usr/initservice/baseinitsvc/initservice.C index dc8380f19..55e395c49 100644 --- a/src/usr/initservice/baseinitsvc/initservice.C +++ b/src/usr/initservice/baseinitsvc/initservice.C @@ -25,6 +25,7 @@ #include #include +#include #include #include #include @@ -77,54 +78,66 @@ errlHndl_t InitService::startTask( const TaskInfo *i_ptask, assert(i_ptask->taskflags.task_type == START_TASK); - tidrc = task_exec( i_ptask->taskname, io_pargs ); // launch the child - if ( static_cast(tidrc) < 0 ) + // Base modules have already been loaded and initialized, + // extended modules have not. + if(i_ptask->taskflags.module_type == EXT_IMAGE) { - // task failed to launch, post an errorlog and dump some trace - /*@ errorlog tag - * @errortype ERRL_SEV_CRITICAL_SYS_TERM - * @moduleid see task list - * @reasoncode START_TASK_FAILED - * @userdata1 task id or task return code - * @userdata2 0 - * - * @devdesc Initialization Service failed to start a task. - * The module id will identify the task. - * - */ - lo_errl = new ERRORLOG::ErrlEntry( - ERRORLOG::ERRL_SEV_CRITICAL_SYS_TERM, // severity - i_ptask->taskflags.module_id, // moduleid - INITSERVICE::START_TASK_FAILED, // reason Code - tidrc, // user1 = tidrc - 0 - ); - TRACDBIN( g_trac_initsvc, - "ERROR starting task:", - i_ptask->taskname, - strlen(i_ptask->taskname) ); - TRACDCOMP( g_trac_initsvc, - "tidrc=%d, errlog p = %p" , - (int16_t)tidrc, lo_errl ); + // load module and call _init() + lo_errl = VFS::module_load( i_ptask->taskname ); + } - } // endif tidrc - else + if( !lo_errl) { - // task launched OK. - TRACDBIN( g_trac_initsvc, - "Task finished OK :", - i_ptask->taskname, - strlen(i_ptask->taskname) ); - TRACDCOMP( g_trac_initsvc, - "task number %d, errlog p = %p", - tidrc, lo_errl ); + tidrc = task_exec( i_ptask->taskname, io_pargs ); // launch the child - if ( io_pargs ) + if ( static_cast(tidrc) < 0 ) { - io_pargs->waitParentSync(); // sync up childtask - } + // task failed to launch, post an errorlog and dump some trace + /*@ errorlog tag + * @errortype ERRL_SEV_CRITICAL_SYS_TERM + * @moduleid see task list + * @reasoncode START_TASK_FAILED + * @userdata1 task id or task return code + * @userdata2 0 + * + * @devdesc Initialization Service failed to start a task. + * The module id will identify the task. + * + */ + lo_errl = new ERRORLOG::ErrlEntry( + ERRORLOG::ERRL_SEV_CRITICAL_SYS_TERM, // severity + i_ptask->taskflags.module_id, // moduleid + INITSERVICE::START_TASK_FAILED, // reason Code + tidrc, // user1 = tidrc + 0 + ); + TRACDBIN( g_trac_initsvc, + "ERROR starting task:", + i_ptask->taskname, + strlen(i_ptask->taskname) ); + TRACDCOMP( g_trac_initsvc, + "tidrc=%d, errlog p = %p" , + (int16_t)tidrc, lo_errl ); + + } // endif tidrc + else + { + // task launched OK. + TRACDBIN( g_trac_initsvc, + "Task finished OK :", + i_ptask->taskname, + strlen(i_ptask->taskname) ); + TRACDCOMP( g_trac_initsvc, + "task number %d, errlog p = %p", + tidrc, lo_errl ); + if ( io_pargs ) + { + io_pargs->waitParentSync(); // sync up childtask + } + } } + // else module load failed. have error log return lo_errl; } @@ -315,6 +328,15 @@ void InitService::init( void *i_ptr ) "task_type==BARRIER" ); // $$TODO break; + + case UNINIT_TASK: + TRACDBIN( g_trac_initsvc, + "task_type=UNINIT_TASK : ", + ptask->taskname, + strlen(ptask->taskname) ); + errl = VFS::module_unload( ptask->taskname ); + break; + default: TRACDCOMP( g_trac_initsvc, "Invalid task_type %d: ", diff --git a/src/usr/initservice/baseinitsvc/initsvctasks.H b/src/usr/initservice/baseinitsvc/initsvctasks.H index bf9c925f4..297386ab7 100644 --- a/src/usr/initservice/baseinitsvc/initsvctasks.H +++ b/src/usr/initservice/baseinitsvc/initsvctasks.H @@ -61,18 +61,31 @@ const TaskInfo g_taskinfolist[] = { } }, + /** + * @brief Extended VFS module + */ + { + "libvfs.so", // taskname + NULL, + { + START_TASK, // start task + BASE_IMAGE, // Base Module + START_VFS_ERRL_ID, // module id for error log + } + }, + // ----- Extended Image ----------------------------------------------------- /** * @brief extinitsvc, initializes extended module area */ { - "libextinitsvc.so" , // taskname + "libextinitsvc.so" , // taskname NULL, // no pointer to fn { - START_TASK, // don't start - EXT_IMAGE, // Ext Module - START_EXTINITSVC_ERRL_ID, // module id for errorlog + START_TASK, // call start() + BASE_IMAGE, // TODO EXT_IMAGE + START_EXTINITSVC_ERRL_ID, // module id for errorlog } }, diff --git a/src/usr/initservice/common/initsvcstructs.H b/src/usr/initservice/common/initsvcstructs.H index f78c093b8..9d169c676 100644 --- a/src/usr/initservice/common/initsvcstructs.H +++ b/src/usr/initservice/common/initsvcstructs.H @@ -43,21 +43,25 @@ namespace INITSERVICE /** * @enum TaskType * - NONE == placeholder, no task - * - START_TASK == task with _start() function entry point + * - INIT_TASK == load and initialize task, but task has no _start() + * (extended image only) + * - START_TASK == BASE_IMAGE: call _start() function entry point + * EXT_IMAGE: call _init(), then _start() * - START_FN == task with function pointer entry point * - BARRIER == set barrier for next N tasks. - * - STOP_TASK == Execute the destructor on the task in extended image. - * ( not implemented yet) + * - UNINIT_TASK == call _fini() to call static destructor(s) on the task. + * (extended image only) * - END_TASK_LIST == last entry in the task list. */ enum TaskType { UNDEFINED_TT = 0, NONE, + INIT_TASK, START_TASK, START_FN, BARRIER, - STOP_TASK, + UNINIT_TASK, END_TASK_LIST, }; diff --git a/src/usr/initservice/extinitsvc/extinitsvc.C b/src/usr/initservice/extinitsvc/extinitsvc.C index db1baef50..1b5612645 100644 --- a/src/usr/initservice/extinitsvc/extinitsvc.C +++ b/src/usr/initservice/extinitsvc/extinitsvc.C @@ -24,7 +24,7 @@ */ #include -#include +#include #include #include #include @@ -132,7 +132,15 @@ void ExtInitSvc::init( void *i_ptr ) ptask->taskname, strlen(ptask->taskname) ); break; - case START_TASK: + case INIT_TASK: + TRACDBIN( g_trac_initsvc, + "task_type==INIT_TASK : ", + ptask->taskname, + strlen(ptask->taskname) ); + errl = VFS::module_load( ptask->taskname ); + break; + + case START_TASK: // call _init(), _start(), stay resident TRACDBIN( g_trac_initsvc, "task_type=START_TASK : ", ptask->taskname, @@ -140,6 +148,7 @@ void ExtInitSvc::init( void *i_ptr ) errl = InitService::getTheInstance().startTask( ptask, &args ); break; + case START_FN: TRACDCOMP( g_trac_initsvc, "task_type==START_FN : %p", @@ -154,6 +163,14 @@ void ExtInitSvc::init( void *i_ptr ) // $$TODO break; + case UNINIT_TASK: + TRACDBIN( g_trac_initsvc, + "task_type=UNINIT_TASK : ", + ptask->taskname, + strlen(ptask->taskname) ); + errl = VFS::module_unload( ptask->taskname ); + break; + default: TRACDCOMP( g_trac_initsvc, "Invalid task_type: %d", diff --git a/src/usr/initservice/extinitsvc/extinitsvctasks.H b/src/usr/initservice/extinitsvc/extinitsvctasks.H index 9c31bc81d..d65abb914 100644 --- a/src/usr/initservice/extinitsvc/extinitsvctasks.H +++ b/src/usr/initservice/extinitsvc/extinitsvctasks.H @@ -30,6 +30,7 @@ namespace INITSERVICE { + // TODO all these will eventuall be in BASE_IMAGE instead of BASE_IMAGE const uint64_t MAX_EXT_TASKS = 25; @@ -45,7 +46,7 @@ const TaskInfo g_exttaskinfolist[] = { NULL, // no pointer to fn { START_TASK, // task type - EXT_IMAGE, // Extended Module + BASE_IMAGE, // Extended Module START_TARGETING_ERRL_ID, // module id } }, @@ -58,7 +59,7 @@ const TaskInfo g_exttaskinfolist[] = { NULL, // no pointer to fn { START_TASK, // task type - EXT_IMAGE, // Extended Module + BASE_IMAGE, // Extended Module EXECUTE_ISTEPS_ERRL_ID, // module id } }, @@ -89,7 +90,7 @@ const TaskInfo CXXTEST_TASK = { NULL, // no pointer to fn { START_TASK, // task type - EXT_IMAGE, // Extended Module + BASE_IMAGE, // Extended Module START_CXXTEST_ERRL_ID, // module id } }; diff --git a/src/usr/makefile b/src/usr/makefile index dc1bffa15..25bf96d4d 100644 --- a/src/usr/makefile +++ b/src/usr/makefile @@ -3,7 +3,7 @@ ROOTPATH = ../.. OBJS = module_init.o SUBDIRS = example.d trace.d cxxtest.d testcore.d errl.d devicefw.d \ - scom.d xscom.d targeting.d initservice.d hwpf.d \ - ecmddatabuffer.d isteps.d pnor.d i2c.d + scom.d xscom.d targeting.d initservice.d hwpf.d \ + ecmddatabuffer.d isteps.d pnor.d vfs.d i2c.d include ${ROOTPATH}/config.mk diff --git a/src/usr/vfs/makefile b/src/usr/vfs/makefile new file mode 100644 index 000000000..2212d9d4f --- /dev/null +++ b/src/usr/vfs/makefile @@ -0,0 +1,8 @@ +ROOTPATH = ../../.. +MODULE = vfs + +OBJS = vfsrp.o + +#SUBDIRS = test.d + +include ${ROOTPATH}/config.mk diff --git a/src/usr/vfs/vfsrp.C b/src/usr/vfs/vfsrp.C new file mode 100644 index 000000000..04e90ecc0 --- /dev/null +++ b/src/usr/vfs/vfsrp.C @@ -0,0 +1,317 @@ +/** + * @file vfsrp.C + * @brief Virtual File system Extended image support + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "vfsrp.H" +#include +#include + +using namespace VFS; + +// Trace definitions +trace_desc_t * g_trac_vfs = NULL; +TRAC_INIT(&g_trac_vfs, VFS_COMP_NAME, 1024); + +/** + * setup _start and handle barrier + */ +TASK_ENTRY_MACRO( VfsRp::init ); + +// ---------------------------------------------------------------------------- + +VfsRp::~VfsRp() +{ + // Unloading of this module currently not supported. + // unregister msg queue? Currently can't do that + // msg_q_destroy(iv_msgQ); +} + +// ---------------------------------------------------------------------------- + +/** + * STATIC initializer of vfs resource provider entry point + */ +void VfsRp::init( void * i_taskArgs ) +{ + errlHndl_t err = NULL; + err = Singleton::instance()._init(); + INITSERVICE::TaskArgs::TaskArgs* args = (INITSERVICE::TaskArgs::TaskArgs*)i_taskArgs; + if(err) + { + args->postErrorLog(err); + } +} + +// ---------------------------------------------------------------------------- + +/** + * Helper function to start vfs messge handler + */ +void VfsRp::msg_handler(void * unused) +{ + Singleton::instance().msgHandler(); +} + +// ---------------------------------------------------------------------------- + +void VfsRp::load_unload(void * i_msg) +{ + Singleton::instance()._load_unload((msg_t*)i_msg); + task_end(); +} + +// ---------------------------------------------------------------------------- + +void VfsRp::exec(void * i_msg) +{ + Singleton::instance()._exec((msg_t*)i_msg); + task_end(); +} + +// ---------------------------------------------------------------------------- + +/** + * Initialze the vfs resource provider + */ +errlHndl_t VfsRp::_init() +{ + errlHndl_t err = NULL; + size_t rc = 0; + iv_msgQ = msg_q_create(); + rc = msg_q_register(iv_msgQ, VFS_MSG); + + // Discover PNOR virtual address of extended image + PNOR::SectionInfo_t l_pnor_info; + + // How will SIDE eventually be determined? TODO + err = PNOR::getSectionInfo(PNOR::HB_EXT_CODE, PNOR::SIDE_A, l_pnor_info); + if(!err) + { + iv_pnor_vaddr = l_pnor_info.vaddr; + + rc = mm_alloc_block + (iv_msgQ, + (void *)VFS_EXTENDED_MODULE_VADDR, + ALIGN_PAGE(l_pnor_info.size) + ); + if(rc == 0) + { + // Start msg_handler + // NOTE: This would be a weak consistancy issues if + // task_create were not a system call. + task_create(VfsRp::msg_handler, NULL); + } + else + { + err = new ERRORLOG::ErrlEntry + ( + ERRORLOG::ERRL_SEV_CRITICAL_SYS_TERM, // severity + VFS::VFS_MODULE_ID, // moduleid + VFS::VFS_ALLOC_VMEM_FAILED, // reason Code + rc, // user1 = rc + 0 // user2 + ); + } + } + + return err; +} + + +// ---------------------------------------------------------------------------- + +void VfsRp::msgHandler() +{ + while(1) + { + msg_t* msg = msg_wait(iv_msgQ); + + switch(msg->type) + { + case VFS_MSG_LOAD: + { + TRACDBIN(g_trac_vfs, "INFO: load module ", + (const char *) msg->data[0], + strlen((const char *) msg->data[0])); + + // run in own task so page faults can be handled + task_create(load_unload, msg); + } + break; + + case VFS_MSG_UNLOAD: + { + TRACDBIN(g_trac_vfs, "INFO: unload module ", + (const char *) msg->data[0], + strlen((const char *) msg->data[0])); + + // run in own task so page faults can be handled + task_create(load_unload, msg); + + } + break; + + case VFS_MSG_EXEC: + { + msg_t * msg1 = (msg_t *) msg->data[0]; + TRACDCOMP(g_trac_vfs, "VFS: Got exec request of %s", + (const char*)msg1->data[0]); + + // run in own task so page faults can be handled + task_create(exec, msg); + + } + break; + + case MSG_MM_RP_READ: + { + uint64_t vaddr = msg->data[0]; + uint64_t paddr = msg->data[1]; //page aligned + + vaddr -= vaddr % PAGE_SIZE; + vaddr -= VFS_EXTENDED_MODULE_VADDR; + memcpy((void *)paddr, (void *)(iv_pnor_vaddr+vaddr), + PAGE_SIZE); + + mm_icache_invalidate((void*)paddr,PAGE_SIZE/8); + + } + msg->data[1] = 0; + msg_respond(iv_msgQ, msg); + break; + + case MSG_MM_RP_WRITE: + assert(0); // not supported now + //msg->data[1] = 0; + //msg_respond(iv_msgQ, msg); + break; + + case MSG_MM_RP_PERM: + msg->data[1] = -EINVAL; + msg_respond(iv_msgQ, msg); + break; + + default: + msg_free(msg); + break; + } + } // while(1) +} + +// ---------------------------------------------------------------------------- + +void VfsRp::_load_unload(msg_t * i_msg) +{ + errlHndl_t err = NULL; + // Find VfsSystemModule + // The TOC for the extended image sits at the start of the image and is + // not location dependant, so just use the one pointed to by iv_pnor_vaddr + // to avoid having to copy it to this block + VfsSystemModule * module = + vfs_find_module + ( + (VfsSystemModule *)iv_pnor_vaddr, //VFS_EXTENDED_MODULE_TABLE_ADDRESS, + (const char *) i_msg->data[0] + ); + + if(module) + { + // TODO mark text page(s) as ro/executable + // TODO mark data page(s) as rw + if(i_msg->type == VFS_MSG_LOAD) + { + if(module->init) + { + (module->init)(NULL); + } + } + else // unload + { + if(module->fini) + { + (module->fini)(NULL); + } + + // TODO mark pages as no access + } + } + else + { + // TODO error log? for now it's probably in the base + // and is aready loaded and initialized. + TRACFBIN(g_trac_vfs, ERR_MRK"Module not found: ", + (const char *) i_msg->data[0], + strlen((const char *) i_msg->data[0]) ); + } + i_msg->data[0] = (uint64_t) err; + msg_respond(iv_msgQ, i_msg); +} + +// ---------------------------------------------------------------------------- + +void VfsRp::_exec(msg_t * i_msg) +{ + msg_t * msg1 = (msg_t *) i_msg->data[0]; + + // The TOC for the extended image sits at the start of the image and is + // not location dependant, so just use the one pointed to by iv_pnor_vaddr + // to avoid having to copy it to this block + VfsSystemModule * module = + vfs_find_module((VfsSystemModule *)(iv_pnor_vaddr + + VFS_EXTENDED_MODULE_TABLE_OFFSET), + (const char*) msg1->data[0]); + + tid_t child = vfs_exec(module, (void*) msg1->data[1]); + + msg_q_t vfsRmsgQ = (msg_q_t) i_msg->data[1]; + + msg1->data[0] = child; + + msg_respond(vfsRmsgQ,msg1); + msg_free(i_msg); +} + + +// -- External interface ------------------------------------------------------ + +errlHndl_t VFS::module_load_unload(const char * i_module, VfsMessages i_msgtype) +{ + errlHndl_t err = NULL; + msg_q_t vfsQ = msg_q_resolve(VFS_MSG); + msg_t* msg = msg_allocate(); + msg->type = i_msgtype; + msg->data[0] = (uint64_t) i_module; + int rc = msg_sendrecv(vfsQ, msg); + + if (0 == rc) + { + err = (errlHndl_t) msg->data[0]; + } + else + { + err = new ERRORLOG::ErrlEntry + ( + ERRORLOG::ERRL_SEV_CRITICAL_SYS_TERM, // severity + VFS::VFS_MODULE_ID, // moduleid + VFS::VFS_LOAD_FAILED, // reason Code + rc, // user1 = msg_sendrecv rc + i_msgtype // user2 = message type + ); + } + + msg_free(msg); + return err; +} + diff --git a/src/usr/vfs/vfsrp.H b/src/usr/vfs/vfsrp.H new file mode 100644 index 000000000..456979e2d --- /dev/null +++ b/src/usr/vfs/vfsrp.H @@ -0,0 +1,90 @@ +#ifndef VFSRP_H +#define VFSRP_H + +#include +#include +#include + +struct msg_t; + +namespace VFS +{ + void vfs_msg_handler(void * unused); + + /** + * Virtual File System Service + */ + class VfsRp + { + public: + + /** + * static init + * @param[in] task args + */ + static void init(void * i_taskArgs); + + protected: + /** + * Ctor + */ + VfsRp() : iv_msgQ(NULL), iv_pnor_vaddr(0) {} + + /** + * Dtor + */ + ~VfsRp(); + + /** + * Start message handler + */ + static void msg_handler(void * unused); + + /** + * Load or Unload a module + * @param[in] i_msg the message + * @note Does not return. calls task_end() + */ + static void load_unload(void * i_msg); + + /** + * Call _start on module + * @param[in] i_msg the message + * @note Does not return. calls task_end() + */ + static void exec(void * i_msg); + + private: // functions + + /** + * Initialize this object + * @return return code on error + */ + errlHndl_t _init(); + + /** + * Message handler + */ + void msgHandler(); + + /** + * Load or Unload a module + * @param[in] i_msg the message + */ + void _load_unload(msg_t * i_msg); + + /** + * Call _start on module + * @param[in] i_msg the message + */ + void _exec(msg_t * i_msg); + + private: // data + + msg_q_t iv_msgQ; //!< message queue + uint64_t iv_pnor_vaddr; //!< virtual address of ext image in PFNOR + }; + +}; // VFS namepsace + +#endif -- cgit v1.2.1