/* * vseg.c - virtual segment (vseg) related operations * * Authors Ghassan Almaless (2008,2009,2010,2011, 2012) * Mohamed Lamine Karaoui (2015) * Alain Greiner (2016) * * Copyright (c) UPMC Sorbonne Universites * * This file is part of ALMOS-MKH. * * ALMOS-MKH.is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2.0 of the License. * * ALMOS-MKH.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 ALMOS-MKH.; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include //////////////////////////////////////////////////////////////////////////////////////// // global variables for display / must be consistent with enum in "vseg.h" //////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////// char * vseg_type_str( uint32_t vseg_type ) { if ( vseg_type == VSEG_TYPE_CODE ) return "CODE"; else if( vseg_type == VSEG_TYPE_DATA ) return "DATA"; else if( vseg_type == VSEG_TYPE_HEAP ) return "HEAP"; else if( vseg_type == VSEG_TYPE_STACK ) return "STACK"; else if( vseg_type == VSEG_TYPE_ANON ) return "ANON"; else if( vseg_type == VSEG_TYPE_FILE ) return "FILE"; else if( vseg_type == VSEG_TYPE_REMOTE ) return "REMOTE"; else if( vseg_type == VSEG_TYPE_KCODE ) return "KCODE"; else if( vseg_type == VSEG_TYPE_KDATA ) return "KDATA"; else if( vseg_type == VSEG_TYPE_KDEV ) return "KDEV"; else return "undefined"; } ///////////////////// vseg_t * vseg_alloc() { kmem_req_t req; req.type = KMEM_VSEG; req.size = sizeof(vseg_t); req.flags = AF_KERNEL; return (vseg_t *)kmem_alloc( &req ); } /////////////////////////////// void vseg_free( vseg_t * vseg ) { kmem_req_t req; req.type = KMEM_VSEG; req.ptr = vseg; kmem_free( &req ); } /////////////////////////////////// void vseg_init( vseg_t * vseg, intptr_t base, intptr_t size, vpn_t vpn_base, vpn_t vpn_size, uint32_t type, cxy_t cxy, fdid_t fdid, uint32_t offset ) { vseg->type = type; vseg->min = base; vseg->max = base + size; vseg->vpn_base = vpn_base; vseg->vpn_size = vpn_size; vseg->mapper = XPTR_NULL; vseg->fdid = fdid; vseg->offset = offset; vseg->cxy = cxy; // set vseg flags depending on type if ( type == VSEG_TYPE_CODE ) { vseg->flags = VSEG_USER | VSEG_EXEC | VSEG_CACHE | VSEG_PRIVATE ; } else if( type == VSEG_TYPE_STACK ) { vseg->flags = VSEG_USER | VSEG_WRITE | VSEG_CACHE | VSEG_PRIVATE ; } else if( type == VSEG_TYPE_DATA ) { vseg->flags = VSEG_USER | VSEG_WRITE | VSEG_CACHE | VSEG_DISTRIB ; } else if( type == VSEG_TYPE_HEAP ) { vseg->flags = VSEG_USER | VSEG_WRITE | VSEG_CACHE | VSEG_DISTRIB ; } else if( type == VSEG_TYPE_REMOTE ) { vseg->flags = VSEG_USER | VSEG_WRITE | VSEG_CACHE ; } else if( type == VSEG_TYPE_ANON ) { vseg->flags = VSEG_USER | VSEG_WRITE | VSEG_CACHE | VSEG_DISTRIB ; } else if( type == VSEG_TYPE_FILE ) { vseg->flags = VSEG_USER | VSEG_WRITE | VSEG_CACHE ; } else if( type == VSEG_TYPE_KCODE ) { vseg->flags = VSEG_EXEC | VSEG_CACHE | VSEG_PRIVATE ; } else if( type == VSEG_TYPE_KDATA ) { vseg->flags = VSEG_WRITE | VSEG_CACHE | VSEG_PRIVATE ; } else { printk("\n[PANIC] in %s : illegal vseg type\n", __FUNCTION__); hal_core_sleep(); } } // end vseg_init() ////////////////////////////////////////// void vseg_init_from_ref( vseg_t * vseg, xptr_t ref ) { // get remote vseg cluster and pointer cxy_t cxy = (cxy_t )GET_CXY( ref ); vseg_t * ptr = (vseg_t *)GET_PTR( ref ); // initialize vseg with remote_read access vseg->type = hal_remote_lw ( XPTR( cxy , &ptr->type ) ); vseg->min = (intptr_t)hal_remote_lpt( XPTR( cxy , &ptr->min ) ); vseg->max = (intptr_t)hal_remote_lpt( XPTR( cxy , &ptr->max ) ); vseg->vpn_base = hal_remote_lw ( XPTR( cxy , &ptr->vpn_base ) ); vseg->vpn_size = hal_remote_lw ( XPTR( cxy , &ptr->vpn_size ) ); vseg->flags = hal_remote_lw ( XPTR( cxy , &ptr->flags ) ); vseg->mapper = (xptr_t) hal_remote_lwd( XPTR( cxy , &ptr->mapper ) ); if( vseg->type == VSEG_TYPE_FILE ) { vseg->fdid = hal_remote_lw( XPTR( cxy , &ptr->fdid ) ); vseg->offset = hal_remote_lw( XPTR( cxy , &ptr->offset ) ); } else { vseg->fdid = 0; vseg->offset = 0; } } // end vseg_init_from_ref() /////////////////////////////// error_t vseg_attach( vmm_t * vmm, vseg_t * vseg ) { // add vseg in radix-tree error_t error = grdxt_insert( &vmm->grdxt , vseg->vpn_base , vseg ); if ( error ) return ENOMEM; // update vseg descriptor vseg->vmm = vmm; // add vseg in vmm list list_add_last( &vmm->vsegs_root , &vseg->list ); return 0; } /////////////////////////////// void vseg_detach( vmm_t * vmm, vseg_t * vseg ) { // remove vseg from radix-tree grdxt_remove( &vmm->grdxt , vseg->vpn_base ); // update vseg descriptor vseg->vmm = NULL; // remove vseg from vmm list list_unlink( &vseg->list ); }