diff options
author | Doug Gilbert <dgilbert@us.ibm.com> | 2012-01-13 09:40:41 -0600 |
---|---|---|
committer | Douglas R. Gilbert <dgilbert@us.ibm.com> | 2012-01-19 14:47:50 -0600 |
commit | 11a2e07a97bb44005dfd8fe8bac690014b3e2a81 (patch) | |
tree | 3a8492a5476e540ced0cbb7cb21c8d16b0936f9f /src | |
parent | 67ab5c65b2caabff6147143a90ab5584573e24ae (diff) | |
download | talos-hostboot-11a2e07a97bb44005dfd8fe8bac690014b3e2a81.tar.gz talos-hostboot-11a2e07a97bb44005dfd8fe8bac690014b3e2a81.zip |
VFS add functions to find module by address and query if module is loaded
Change-Id: I471a2a773d42f11ab973f42ca701c8be5191d776
Reviewed-on: http://gfw160.austin.ibm.com:8080/gerrit/611
Tested-by: Jenkins Server
Reviewed-by: Daniel M. Crowell <dcrowell@us.ibm.com>
Reviewed-by: Douglas R. Gilbert <dgilbert@us.ibm.com>
Diffstat (limited to 'src')
-rw-r--r-- | src/include/sys/vfs.h | 15 | ||||
-rw-r--r-- | src/include/usr/vfs/vfs.H | 14 | ||||
-rw-r--r-- | src/sys/vfs/vfs_init.C | 24 | ||||
-rw-r--r-- | src/usr/vfs/test/vfstest.H | 32 | ||||
-rw-r--r-- | src/usr/vfs/vfsrp.C | 113 | ||||
-rw-r--r-- | src/usr/vfs/vfsrp.H | 26 |
6 files changed, 206 insertions, 18 deletions
diff --git a/src/include/sys/vfs.h b/src/include/sys/vfs.h index 155851398..3094a1707 100644 --- a/src/include/sys/vfs.h +++ b/src/include/sys/vfs.h @@ -69,8 +69,8 @@ enum VfsMessages VFS_MSG_REGISTER_MSGQ, //!< Message to VFS_ROOT to register a message queue VFS_MSG_RESOLVE_MSGQ, //!< Message to VFS_ROOT to find a message queue VFS_MSG_EXEC, //!< Message to VFS_ROOT execute a module - VFS_MSG_LOAD, //!< Message to VFS_MSG to load a module - VFS_MSG_UNLOAD, //!< Message to VFS_MSG to unload a module + VFS_MSG_LOAD, //!< Message to vfsrp to load a module + VFS_MSG_UNLOAD, //!< Message to vfsrp to unload a module }; struct VfsSystemModule @@ -81,7 +81,7 @@ struct VfsSystemModule void (*fini)(void*); //!< ptr to fini() uint64_t * text; //!< ptr to text (code) section uint64_t * data; //!< ptr to data section - uint64_t byte_count; //!< no. of memory pages used + uint64_t byte_count; //!< no. of bytes in module }; extern VfsSystemModule VFS_MODULES[VFS_MODULE_MAX]; @@ -102,6 +102,15 @@ extern uint64_t VFS_LAST_ADDRESS; VfsSystemModule * vfs_find_module(VfsSystemModule * i_table, const char * i_name); /** + * Find the VfsSystemModule for the given address + * @param[in] i_table The VFS module table to look in + * @param[in] i_vaddr The virtual address + * @return VrsSytemModule ptr for the module | NULL if not found + */ +VfsSystemModule * vfs_find_address(VfsSystemModule * i_table, + const void * i_vaddr); + +/** * Get the module's start routine * @param[in] i_module VfsSystemModule data for the module * @return Function pointer of module's start or negative value on error. diff --git a/src/include/usr/vfs/vfs.H b/src/include/usr/vfs/vfs.H index c916eb8ce..f65bfd51c 100644 --- a/src/include/usr/vfs/vfs.H +++ b/src/include/usr/vfs/vfs.H @@ -83,6 +83,20 @@ namespace VFS */ errlHndl_t module_address(const char * i_name, const char *& o_address, size_t & o_size); + /** + * Get the module name associated with an address + * @param[in] i_vaddr, The virtual address + * @returns ptr to module name or NULL if not found + */ + const char * module_find_name(const void * i_vaddr); + + /** + * Query if module is loaded + * @param[in] module name + * @returns [true|false] + */ + bool module_is_loaded(const char * i_name); + }; #endif diff --git a/src/sys/vfs/vfs_init.C b/src/sys/vfs/vfs_init.C index 91e09876f..e0cf844fa 100644 --- a/src/sys/vfs/vfs_init.C +++ b/src/sys/vfs/vfs_init.C @@ -119,4 +119,28 @@ VfsSystemModule * vfs_find_module(VfsSystemModule * i_table, return ret; } +// ---------------------------------------------------------------------------- + +VfsSystemModule * vfs_find_address(VfsSystemModule * i_table, + const void * i_vaddr) +{ + VfsSystemModule * module = i_table; + VfsSystemModule * ret = NULL; + + const uint8_t * vaddr = reinterpret_cast<const uint8_t *>(i_vaddr); + + while('\0' != module->module[0]) + { + const uint8_t * first = reinterpret_cast<const uint8_t *>(module->text); + const uint8_t * last = first + module->byte_count; + + if(vaddr >= first && vaddr < last) + { + ret = module; + break; + } + ++module; + } + return ret; +} diff --git a/src/usr/vfs/test/vfstest.H b/src/usr/vfs/test/vfstest.H index 5e33a0b33..3f9644f27 100644 --- a/src/usr/vfs/test/vfstest.H +++ b/src/usr/vfs/test/vfstest.H @@ -71,6 +71,38 @@ class VfsTest: public CxxTest::TestSuite TS_FAIL("module_unload failed"); } } + + void test_findModule(void) + { + size_t size = 0; + const char * addr = NULL; + const char * name = "testdata"; + + errlHndl_t err = VFS::module_address(name , addr, size); + if (err) + { + TS_FAIL("module_address failed"); + ERRORLOG::errlCommit(err,VFS_COMP_ID); + } + + name = VFS::module_find_name(addr); + TS_TRACE("VFS module @ %p is %s",addr,name); + + if(strcmp(name,"testdata") != 0) + { + TS_FAIL("VFS find module by address failed!"); + } + + if(VFS::module_is_loaded(name)) + { + TS_TRACE("VFS module %s is loaded",name); + TS_FAIL("VFS module should NOT be loaded"); + } + else + { + TS_TRACE("VFS module %s is not loaded",name); + } + } }; diff --git a/src/usr/vfs/vfsrp.C b/src/usr/vfs/vfsrp.C index e060c7b80..be9364965 100644 --- a/src/usr/vfs/vfsrp.C +++ b/src/usr/vfs/vfsrp.C @@ -263,33 +263,56 @@ void VfsRp::_load_unload(msg_t * i_msg) { int rc = 0; + // don't want the possibility of a function called in this module + // until it's completely loaded and inited, so hold + // off any query or other operation. + mutex_lock(&iv_mutex); + + ModuleList_t::iterator mod_itr = + std::find(iv_loaded.begin(),iv_loaded.end(),module); + if(i_msg->type == VFS_MSG_LOAD) { - rc = vfs_module_perms(module); - - if(!rc) + if(mod_itr == iv_loaded.end()) // make sure it's not already loaded { - if(module->init) + // Set mem access parms + rc = vfs_module_perms(module); + if(!rc) { - (module->init)(NULL); + iv_loaded.push_back(module); + + if(module->init) + { + (module->init)(NULL); + } + } } } else // unload { - if(module->fini) + if(mod_itr != iv_loaded.end()) // Loaded { - (module->fini)(NULL); - } + iv_loaded.erase(mod_itr); - rc = mm_set_permission(module->text, - ALIGN_PAGE(module->byte_count), - NO_ACCESS); + if(module->fini) + { + (module->fini)(NULL); + } + + rc = mm_set_permission(module->text, + ALIGN_PAGE(module->byte_count), + NO_ACCESS); - rc = mm_remove_pages(RELEASE, - module->text, - ALIGN_PAGE(module->byte_count)); + rc = mm_remove_pages(RELEASE, + module->text, + ALIGN_PAGE(module->byte_count)); + } + // else module was not loaded } + + mutex_unlock(&iv_mutex); + if(rc) { /*@ errorlog tag @@ -399,6 +422,57 @@ const VfsSystemModule * VfsRp::get_vfs_info(const char * i_name) const // ---------------------------------------------------------------------------- +const char * VfsRp::get_name_from_address(const void * i_vaddr) const +{ + const char * result = NULL; + + VfsSystemModule * module = vfs_find_address + ((VfsSystemModule *)(iv_pnor_vaddr + VFS_EXTENDED_MODULE_TABLE_OFFSET), + i_vaddr); + + if(!module) // look in the base modules + { + module = vfs_find_address(VFS_MODULES,i_vaddr); + } + if(module) + { + result = module->module; + } + return result; +} + +// ---------------------------------------------------------------------------- + +bool VfsRp::is_module_loaded(const char * i_name) +{ + bool result = false; + const VfsSystemModule * module = get_vfs_info(i_name); + if(module) + { + mutex_lock(&iv_mutex); + ModuleList_t::const_iterator i = + std::find(iv_loaded.begin(),iv_loaded.end(),module); + if(i != iv_loaded.end()) + { + result = true; + } + mutex_unlock(&iv_mutex); + } + if(!result) // look in the base + { + module = vfs_find_module(VFS_MODULES,i_name); + if(module) + { + // all base modules are always loaded + result = true; + } + } + + return result; +} + +// ---------------------------------------------------------------------------- + void VfsRp::get_test_modules(std::vector<const char *> & o_list) const { o_list.clear(); @@ -518,3 +592,14 @@ errlHndl_t VFS::module_address(const char * i_name, const char *& o_address, siz return err; } +const char * VFS::module_find_name(const void * i_vaddr) +{ + return Singleton<VfsRp>::instance().get_name_from_address(i_vaddr); +} + +bool VFS::module_is_loaded(const char * i_name) +{ + return Singleton<VfsRp>::instance().is_module_loaded(i_name); +} + + diff --git a/src/usr/vfs/vfsrp.H b/src/usr/vfs/vfsrp.H index c5a74c91f..8492f559d 100644 --- a/src/usr/vfs/vfsrp.H +++ b/src/usr/vfs/vfsrp.H @@ -27,6 +27,8 @@ #include <builtins.h> #include <errl/errltypes.H> #include <sys/msg.h> +#include <vector> +#include <sys/sync.h> struct msg_t; @@ -68,11 +70,28 @@ namespace VFS */ const VfsSystemModule * get_vfs_info(const char * i_name) const; + /** + * Get the module name that contains the given address + * @param[in] i_vaddr The virtual address + * @return ptr to the module name or NULL if it's not found + */ + const char * get_name_from_address(const void * i_vaddr) const; + + /** + * Query if a module is loaded + * @param[in] i_name The module name + * @return [true|false] + */ + bool is_module_loaded(const char * i_name); + protected: /** * Ctor */ - VfsRp() : iv_msgQ(NULL), iv_pnor_vaddr(0) {} + VfsRp() : iv_msgQ(NULL), iv_pnor_vaddr(0) + { + mutex_init(&iv_mutex); + } /** * Dtor @@ -127,6 +146,11 @@ namespace VFS msg_q_t iv_msgQ; //!< message queue uint64_t iv_pnor_vaddr; //!< virtual address of ext image in PFNOR + + typedef std::vector<VfsSystemModule *> ModuleList_t; + + mutex_t iv_mutex; //!< lock for iv_loaded + ModuleList_t iv_loaded; //!< Loaded modules }; }; // VFS namepsace |