diff options
author | dgilbert <dgilbert@us.ibm.com> | 2011-07-28 16:42:28 -0500 |
---|---|---|
committer | Douglas R. Gilbert <dgilbert@us.ibm.com> | 2011-08-17 14:22:39 -0500 |
commit | c56648379cde6ea3bcfac07923bb560734c6e16f (patch) | |
tree | 81ee3d5abaa130d0f1e36e038c3a344e11f55ce0 /src/usr/vfs | |
parent | 20b03fdaeb7414fdf9d43634976ca1ab5fbac7f1 (diff) | |
download | talos-hostboot-c56648379cde6ea3bcfac07923bb560734c6e16f.tar.gz talos-hostboot-c56648379cde6ea3bcfac07923bb560734c6e16f.zip |
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 <iawillia@us.ibm.com>
Reviewed-by: Daniel M. Crowell <dcrowell@us.ibm.com>
Diffstat (limited to 'src/usr/vfs')
-rw-r--r-- | src/usr/vfs/makefile | 8 | ||||
-rw-r--r-- | src/usr/vfs/vfsrp.C | 317 | ||||
-rw-r--r-- | src/usr/vfs/vfsrp.H | 90 |
3 files changed, 415 insertions, 0 deletions
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 <limits.h> +#include <string.h> +#include <errno.h> +#include <sys/msg.h> +#include <sys/vfs.h> +#include <vfs/vfs.H> +#include <vfs/vfs_reasoncodes.H> +#include <sys/task.h> +#include <sys/mm.h> +#include <initservice/taskargs.H> +#include <trace/interface.H> +#include "vfsrp.H" +#include <pnor/pnorif.H> +#include <util/align.H> + +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<VfsRp>::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<VfsRp>::instance().msgHandler(); +} + +// ---------------------------------------------------------------------------- + +void VfsRp::load_unload(void * i_msg) +{ + Singleton<VfsRp>::instance()._load_unload((msg_t*)i_msg); + task_end(); +} + +// ---------------------------------------------------------------------------- + +void VfsRp::exec(void * i_msg) +{ + Singleton<VfsRp>::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 <stdint.h> +#include <builtins.h> +#include <errl/errltypes.H> + +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 |