source: soft/giet_vm/memo/src/memo.cpp @ 378

Last change on this file since 378 was 255, checked in by meunier, 11 years ago
  • Added a syscall and some user functions to manipulate the Simulation Helper
  • Changed the the way the Vseg -> Pseg mapping is made during the boot to better utilize the address space (+ adaptation of the algorithm in memo)
  • Fixed a bug in boot_init (vobj_init): the vobj initialization could only be made for the first application (ptpr was not changed)
File size: 20.8 KB
Line 
1/* -*- c++ -*-
2 *
3 * GIET_VM_LGPL_HEADER_BEGIN
4 *
5 * This file is part of GIET_VM, GNU LGPLv2.1.
6 *
7 * GIET_VM is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU Lesser General Public License as published
9 * by the Free Software Foundation; version 2.1 of the License.
10 *
11 * GIET_VM is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with GIET_VM; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 * 02110-1301 USA
20 *
21 * GIET_VM_LGPL_HEADER_END
22 *
23 * Copyright (c) UPMC, Lip6, SoC
24 *         Mohamed Lamine KARAOUI <Mohamed.Karaoui@lip6.fr>, 2012
25 */
26
27#include <string.h>
28#include <cassert>
29#include <sstream>
30#include <fstream>
31#include <ios>
32#include <iostream>
33#include <cstdarg>
34#include <cassert>
35#include <iomanip>
36
37
38#include "exception.h"
39#include "memo.h"
40
41//#define MOVER_DEBUG
42
43size_t PSeg::m_pageSize;
44
45
46////////////////////////////////////////////
47MeMo::MeMo(const std::string     &filename, 
48           const size_t          pageSize)
49        : m_path(filename),
50          m_pathHandler(filename),
51          m_ginit(false),
52          m_generator(new elfpp::object())
53{
54    PSeg::setPageSize(pageSize);
55
56    // loading map_info blob
57    m_data = std::malloc(bin_size(m_path));
58    if ( !m_data )
59        throw exception::RunTimeError("malloc failed... No memory space");
60
61    m_size = load_bin(m_path, m_data);
62
63    // checking signature
64    mapping_header_t*   header = (mapping_header_t*)m_data; 
65    if((IN_MAPPING_SIGNATURE != header->signature))
66    {
67        std::cout  << "wrong signature " 
68                   << std::hex <<header->signature
69                   << ", should be:"<< IN_MAPPING_SIGNATURE << std::endl;
70        exit(1);
71    }
72
73#ifdef MOVER_DEBUG
74    std::cout << "Binary file path: " << m_path << std::endl;
75    print_mapping_info(m_data);
76#endif
77
78    buildMap(m_data);
79   
80#ifdef MOVER_DEBUG
81    std::cout << "parsing done" << std::endl ;
82#endif
83
84#ifdef MOVER_DEBUG
85    print_mapping();
86    std::cout << *this << std::endl;
87#endif
88
89    m_psegh.check();
90#ifdef MOVER_DEBUG
91    std::cout << "checking done" << std::endl ;
92#endif
93
94}
95
96/////////////////////////////////////////
97void MeMo::print(std::ostream &o) const
98{
99    std::cout << "All sections:" << std::endl;
100    FOREACH(sect, m_generator->get_section_table())
101    {
102        assert(&*sect != NULL);
103        std::cout << *sect << std::endl; 
104    }
105}
106
107////////////////////////////////
108void MeMo::print_mapping() const
109{
110    std::cout << m_psegh << std::endl;
111}
112
113////////////////////////////////////////////////////////////////////////////////
114elfpp::section* MeMo::get_sect_by_addr(elfpp::object *loader, unsigned int addr)
115{
116    FOREACH( sect, loader->get_section_table() )
117    {
118        assert(&*sect != NULL);
119        elfpp::sh_flags_e eflags = sect->get_flags();
120        if ( !(eflags & elfpp::SHF_ALLOC) )
121            continue;
122        if(sect->get_load_address() == addr) //load_addr ?
123        {
124            return (&*sect);
125        }
126    }
127    return NULL;
128}
129
130/////////////////////////////////////////////////
131void MeMo::buildSoft(const std::string &filename)
132{
133    if(!m_ginit)
134        throw exception::RunTimeError(std::string("Can't get generator! ") );
135
136    m_generator->write(filename);
137
138}
139
140/////////////////////////////////////////////////////////
141size_t MeMo::load_bin(std::string filename, void* buffer)
142{
143
144#ifdef MOVER_DEBUG
145    std::cout  << "Loading binary blob from file '" << filename << "'" << std::endl;
146#endif
147
148    std::ifstream input(filename.c_str(), std::ios_base::binary|std::ios_base::in);
149
150    if ( ! input.good() )
151        throw exception::RunTimeError(std::string("Can't open the file: ") + filename);
152
153    input.seekg( 0, std::ifstream::end );
154    size_t size = input.tellg();
155    input.seekg( 0, std::ifstream::beg );
156
157    if ( !buffer )
158        throw exception::RunTimeError("Empty buffer!");
159
160    input.read( (char*)buffer, size );
161
162    input.close();
163
164    return size;
165}
166
167
168/* get the size of the content of the filename */
169//////////////////////////////////////////
170size_t MeMo::bin_size(std::string filename)
171{
172
173#ifdef MOVER_DEBUG
174    std::cout  << "Trying to get the size of the binary blob '" << filename << "'" << std::endl;
175#endif
176
177    std::ifstream input(filename.c_str(), std::ios_base::binary|std::ios_base::in);
178
179    if ( ! input.good() )
180        throw exception::RunTimeError(std::string("Can't open the file: ") + filename);
181
182    input.seekg( 0, std::ifstream::end );
183    size_t size = input.tellg();
184    input.seekg( 0, std::ifstream::beg );
185
186    input.close();
187
188    return size;
189}
190
191
192/////////////
193MeMo::~MeMo()
194{
195    //std::cout << "Deleted MeMo " << *this << std::endl;
196    //std::free(m_data);//should be done by the elfpp driver since we passed the pointer
197    std::map<std::string, elfpp::object*>::iterator l;
198    for(l = m_loaders.begin(); l != m_loaders.end(); l++)
199    {
200        delete (*l).second;
201    }
202    //delete m_generator;
203}
204
205
206/////////////////////////////////////////////////////////////////////////////
207// various mapping_info data structure access functions
208/////////////////////////////////////////////////////////////////////////////
209mapping_cluster_t* MeMo::get_cluster_base( mapping_header_t* header )
210{
211    return   (mapping_cluster_t*) ((char*)header +
212                                  MAPPING_HEADER_SIZE);
213}
214/////////////////////////////////////////////////////////////////////////////
215mapping_pseg_t* MeMo::get_pseg_base( mapping_header_t* header )
216{
217    return   (mapping_pseg_t*)    ((char*)header +
218                                  MAPPING_HEADER_SIZE +
219                                  MAPPING_CLUSTER_SIZE*header->clusters);
220}
221/////////////////////////////////////////////////////////////////////////////
222mapping_vspace_t* MeMo::get_vspace_base( mapping_header_t* header )
223{
224    return   (mapping_vspace_t*)  ((char*)header +
225                                  MAPPING_HEADER_SIZE +
226                                  MAPPING_CLUSTER_SIZE*header->clusters +
227                                  MAPPING_PSEG_SIZE*header->psegs);
228}
229/////////////////////////////////////////////////////////////////////////////
230mapping_vseg_t* MeMo::get_vseg_base( mapping_header_t* header )
231{
232    return   (mapping_vseg_t*)    ((char*)header +
233                                  MAPPING_HEADER_SIZE +
234                                  MAPPING_CLUSTER_SIZE*header->clusters +
235                                  MAPPING_PSEG_SIZE*header->psegs +
236                                  MAPPING_VSPACE_SIZE*header->vspaces);
237}
238/////////////////////////////////////////////////////////////////////////////
239mapping_vobj_t* MeMo::get_vobj_base( mapping_header_t* header )
240{
241    return   (mapping_vobj_t*)    ((char*)header +
242                                  MAPPING_HEADER_SIZE +
243                                  MAPPING_CLUSTER_SIZE*header->clusters +
244                                  MAPPING_PSEG_SIZE*header->psegs +
245                                  MAPPING_VSPACE_SIZE*header->vspaces +
246                                  MAPPING_VSEG_SIZE*header->vsegs);
247}
248
249/////////////////////////////////////////////////////////////////////////////
250// print the content of the mapping_info data structure
251////////////////////////////////////////////////////////////////////////
252void MeMo::print_mapping_info(void* desc)
253{
254    mapping_header_t*   header = (mapping_header_t*)desc; 
255
256    mapping_pseg_t*         pseg    = get_pseg_base( header );;
257    mapping_vspace_t*   vspace  = get_vspace_base ( header );;
258    mapping_vseg_t*         vseg    = get_vseg_base ( header );
259    mapping_vobj_t*         vobj    = get_vobj_base ( header );
260
261    // header
262    std::cout << std::hex << "mapping_info" << std::dec << std::endl
263              << " + signature = " << header->signature << std::endl
264              << " + name      = " << (char*)header->name      << std::endl
265              << " + clusters  = " << header->clusters  << std::endl
266              << " + psegs     = " << header->psegs     << std::endl
267              << " + vspaces   = " << header->vspaces   << std::endl
268              << " + globals   = " << header->globals   << std::endl
269              << " + vsegs     = " << header->vsegs     << std::endl
270              << " + vobjs     = " << header->vsegs     << std::endl
271              << " + tasks     = " << header->tasks     << std::endl;
272
273    // psegs
274    for ( size_t pseg_id = 0 ; pseg_id < header->psegs ; pseg_id++ )
275    {
276        std::cout << "pseg " << pseg[pseg_id].name << std::hex << std::endl
277                  << " + base   = " << pseg[pseg_id].base   << std::endl
278                  << " + length = " << pseg[pseg_id].length << std::endl ;
279    }
280
281    // globals
282    for ( size_t vseg_id = 0 ; vseg_id < header->globals ; vseg_id++ )
283    {
284        std::cout << std::endl;
285        //std::cout << vseg[vseg_id].psegid << std::endl;
286        std::cout << "global vseg "   << vseg[vseg_id].name << std::hex << std::endl
287                  << " + vbase    = " << vseg[vseg_id].vbase << std::endl
288                  << " + length   = " << vseg[vseg_id].length << std::endl
289                  << " + mode     = " << (size_t)vseg[vseg_id].mode << std::endl
290                  << " + ident    = " << (bool)vseg[vseg_id].ident << std::endl
291                  << " + psegname = " << pseg[vseg[vseg_id].psegid].name << std::endl;
292        for( size_t vobj_id = vseg[vseg_id].vobj_offset ; 
293                    vobj_id < vseg[vseg_id].vobj_offset + vseg[vseg_id].vobjs ; 
294                    vobj_id++ )
295        {
296            std::cout << "\t vobj "        << vobj[vobj_id].name    << std::endl
297                      << "\t + index   = " << std::dec << vobj_id   << std::endl
298                      << "\t + type    = " << vobj[vobj_id].type    << std::endl
299                      << "\t + length  = " << vobj[vobj_id].length  << std::endl
300                      << "\t + align   = " << vobj[vobj_id].align   << std::endl
301                      << "\t + binpath = " << vobj[vobj_id].binpath << std::endl
302                      << "\t + init    = " << vobj[vobj_id].init    << std::endl;
303        }
304    }
305
306    // vspaces
307    for ( size_t vspace_id = 0 ; vspace_id < header->vspaces ; vspace_id++ )
308    {
309        std::cout << "***vspace "  << vspace[vspace_id].name   << std::endl
310                  << " + vsegs = " <<  vspace[vspace_id].vsegs << std::endl
311                  << " + vobjs = " <<  vspace[vspace_id].vobjs << std::endl
312                  << " + tasks = " <<  vspace[vspace_id].tasks << std::endl;
313
314        for ( size_t vseg_id = vspace[vspace_id].vseg_offset ; 
315              vseg_id < (vspace[vspace_id].vseg_offset + vspace[vspace_id].vsegs) ; 
316              vseg_id++ )
317        {
318            std::cout << "\t vseg " << vseg[vseg_id].name  << std::endl
319                      << "\t + vbase    = " << vseg[vseg_id].vbase             << std::endl
320                      << "\t + length   = " << vseg[vseg_id].length            << std::endl
321                      << "\t + mode     = " << (size_t)vseg[vseg_id].mode      << std::endl
322                      << "\t + ident    = " << (bool)vseg[vseg_id].ident       << std::endl
323                      << "\t + psegname = " << pseg[vseg[vseg_id].psegid].name << std::endl;
324            for(size_t vobj_id = vseg[vseg_id].vobj_offset ; 
325                       vobj_id < vseg[vseg_id].vobj_offset + vseg[vseg_id].vobjs ; 
326                       vobj_id++ )
327            {
328                std::cout << "\t\t vobj "      << vobj[vobj_id].name      << std::endl
329                          << "\t\t + index   = " << std::dec << vobj_id   << std::endl
330                          << "\t\t + type    = " << vobj[vobj_id].type    << std::endl
331                          << "\t\t + length  = " << vobj[vobj_id].length  << std::endl
332                          << "\t\t + align   = " << vobj[vobj_id].align   << std::endl
333                          << "\t\t + binpath = " << vobj[vobj_id].binpath << std::endl
334                          << "\t\t + init    = " << vobj[vobj_id].init    << std::endl;
335            }
336        }
337
338    }
339} // end print_mapping_info()
340
341
342//////////////////////////////////////////
343void MeMo::vseg_map( mapping_vseg_t* vseg)
344{
345    mapping_vobj_t * vobj = get_vobj_base((mapping_header_t*) m_data );
346    PSeg            * ps = &(m_psegh.get(vseg->psegid));
347    elfpp::section * sect = NULL;
348    size_t           cur_vaddr;
349    paddr_t          cur_length;
350    bool             first = true;
351    bool             aligned = false;
352    VSeg *           vSO = new VSeg;
353    mapping_vobj_t * cur_vobj;
354
355    vSO->m_name = std::string(vseg->name);
356    vSO->m_vma  = vseg->vbase;
357    vSO->m_lma  = 0;
358
359    cur_vaddr = vseg->vbase;
360    cur_length = 0; // curr_length of the vseg; a new vseg is necessarily aligned on a page boundary
361
362#ifdef MOVER_DEBUG
363    std::cout << "--------------- vseg_map "<< vseg->name <<" ------------------" << std::endl;
364#endif
365
366    for (size_t vobj_id = vseg->vobj_offset; 
367          vobj_id < (vseg->vobj_offset + vseg->vobjs); vobj_id++)
368    {
369        cur_vobj = &vobj[vobj_id];
370
371#ifdef MOVER_DEBUG
372        std::cout << std::hex << "current vobj("<< vobj_id <<"): " << cur_vobj->name
373                  << " (" <<cur_vobj->vaddr << ")"
374                  << " size: "<< cur_vobj->length
375                  << " type: " <<  cur_vobj->type << std::endl;
376#endif
377        if (cur_vobj->type == VOBJ_TYPE_BLOB)
378        {
379            size_t blob_size;
380            std::string filePath(m_pathHandler.getFullPath(std::string(cur_vobj->binpath)));
381
382#ifdef MOVER_DEBUG
383            std::cout << std::hex << "Handling: " << filePath << " ..." << std::endl;
384#endif
385
386            if (!filePath.compare(m_path))    // local blob: map_info
387            {
388#ifdef MOVER_DEBUG
389                std::cout << "Found the vseg of the mapping info" << std::endl;
390#endif
391                blob_size = this->m_size;
392                assert((blob_size >0) and "MAPPING INFO file is empty !?");
393            }
394            else
395            {
396#ifdef MOVER_DEBUG
397                std::cout << "Found an BLOB vseg" << std::endl;
398#endif
399                blob_size = bin_size(filePath);
400            }
401
402            // creating a new section
403            sect = new elfpp::section(*m_generator, elfpp::SHT_PROGBITS);
404
405            sect->set_name(std::string(cur_vobj->name));
406            sect->set_flags(elfpp::SHF_ALLOC | elfpp::SHF_WRITE);
407            sect->set_size(blob_size);  //do the malloc for the get_content fonction
408
409            assert(sect->get_content());//check allocation
410
411            if (!filePath.compare(m_path)) {   //local blob: map_info
412                //memcpy(sect->get_content(), m_data, sect->get_size());
413                /* this way the modification of the elf size are propageted to the giet */
414                sect->set_content(this->m_data);
415            }
416            else
417            {
418                load_bin(filePath, sect->get_content());
419            }
420
421
422            if (blob_size > cur_vobj->length)
423            {
424                std::cout << std::hex << "!!! Warning, specified blob type vobj ("<<
425                cur_vobj->name  <<") size is "<< cur_vobj->length << ", the actual size is "
426                << blob_size  << " !!!" <<std::endl;
427                assert(0 and "blob vobj length smaller than the actual content" );//???
428            }
429
430            cur_vobj->length = blob_size; //set the true size of this BLOB vobj
431
432            vSO->m_file = filePath;
433            vSO->m_loadable = true;
434        }
435        else if (cur_vobj->type == VOBJ_TYPE_ELF)
436        {
437            if (!first)
438                throw exception::RunTimeError(std::string("elf vobj type, must be placed first in a vseg"));
439
440            size_t elf_size;
441            std::string filePath(m_pathHandler.getFullPath(std::string(cur_vobj->binpath)));
442#ifdef MOVER_DEBUG
443            std::cout << "Handling: " << filePath << " ..." << std::endl;
444            std::cout << "Found an ELF vseg" << std::endl;
445#endif
446            if (m_loaders.count(filePath) == 0)
447                m_loaders[filePath] = new elfpp::object(filePath);
448            elfpp::object * loader = m_loaders[filePath]; //TODO:free!?
449
450            sect =  new elfpp::section(*get_sect_by_addr(loader, cur_vaddr)); //copy: for the case we replicate the code
451            if (!sect)
452            {
453                std::cerr << "No section found for " << cur_vobj->name << " at "<< cur_vaddr << std::endl;
454                exit(-1);
455            }
456
457            sect->set_name(std::string(cur_vobj->name));
458
459
460            elf_size = sect->get_size();
461            assert((elf_size > 0) and "ELF section empty ?");
462
463            if (!m_ginit)
464            {
465                /** Initailising the header of the generator from the first binary,
466                ** we suppose that the header is the same for all the binarys **/
467                m_generator->copy_info(*loader, 64);
468                m_ginit = true;
469            }
470
471            if (elf_size > cur_vobj->length)
472            {
473                std::cout << "Warning, specified elf type vobj (" <<
474                cur_vobj->name  << ") size is " << cur_vobj->length << ", the actual size is "
475                << elf_size  << std::endl;
476                assert((0) and "elf vobj length smaller than the actual content");
477            }
478
479            cur_vobj->length = elf_size;//set the true size of this ELF vobj
480
481            vSO->m_file = filePath;
482            vSO->m_loadable = true;
483        }
484
485        //aligning the vobj->paddr if necessary
486        if (cur_vobj->align)
487        {
488            cur_length = PSeg::align(cur_length, cur_vobj->align);
489            aligned = true;
490        }
491
492        cur_vaddr += cur_vobj->length;
493        cur_length += cur_vobj->length;
494        first = false;
495    }
496
497    assert(cur_vaddr >= vseg->vbase);
498
499    vSO->m_length = cur_length; //pageAlign is done by the psegs
500    vSO->m_ident = vseg->ident;
501    vSO->m_align = vobj[vseg->vobj_offset].align;
502
503    //set the lma for vseg that are not peripherals
504    if (ps->type() != PSEG_TYPE_PERI)
505    {
506        if (vseg->ident != 0) ps->addIdent(*vSO);
507        else                  ps->add(*vSO);
508    }
509
510    if (!sect) return;
511
512#ifdef MOVER_DEBUG
513    std::cout << "section: "<< *sect <<"\n seted to: " << (*vSO) << std::endl;
514#endif
515
516    sect->set_vaddr((*vSO).lma());
517    m_generator->add_section(*sect);
518
519} // end vseg_map()
520 
521
522///////////////////////////////
523void MeMo::buildMap(void * desc)
524{
525    mapping_header_t * header  = (mapping_header_t *) desc; 
526
527    mapping_cluster_t * cluster = get_cluster_base(header);     
528    mapping_vspace_t *  vspace  = get_vspace_base(header);     
529    mapping_pseg_t *    pseg    = get_pseg_base(header); 
530    mapping_vseg_t *    vseg    = get_vseg_base(header);
531
532    // get the psegs
533
534#ifdef MOVER_DEBUG
535    std::cout << "\n******* Storing Pseg information *********\n" << std::endl;
536#endif
537
538    for (size_t cluster_id = 0; cluster_id < header->clusters; cluster_id++) {
539        for (size_t pseg_id = cluster[cluster_id].pseg_offset;
540              pseg_id < cluster[cluster_id].pseg_offset + cluster[cluster_id].psegs;
541              pseg_id++) {
542            std::string name(pseg[pseg_id].name);
543            PSeg *ps = new PSeg(name, 
544                                pseg[pseg_id].base, 
545                                pseg[pseg_id].length, 
546                                pseg[pseg_id].type);
547            m_psegh.m_pSegs.push_back(*ps);
548        }
549    }
550
551    // map global vsegs
552
553#ifdef MOVER_DEBUG
554    std::cout << "\n******* mapping global vsegs *********\n" << std::endl;
555#endif
556
557    // Mapping identity segments first
558    for (size_t vseg_id = 0; vseg_id < header->globals; vseg_id++) {
559        if (vseg[vseg_id].ident == 1) {
560            vseg_map(&vseg[vseg_id]);
561        }
562    }
563
564    // Mapping non-identity segments second
565    for (size_t vseg_id = 0; vseg_id < header->globals; vseg_id++) {
566        if (vseg[vseg_id].ident == 0) {
567            vseg_map(&vseg[vseg_id]);
568        }
569    }
570
571
572
573    // loop on virtual spaces to map private vsegs
574    for (size_t vspace_id = 0; vspace_id < header->vspaces; vspace_id++) {
575#ifdef MOVER_DEBUG
576        std::cout << "\n******* mapping all vsegs of " << vspace[vspace_id].name << " *********\n" << std::endl;
577#endif
578        for (size_t vseg_id = vspace[vspace_id].vseg_offset; 
579             vseg_id < (vspace[vspace_id].vseg_offset + vspace[vspace_id].vsegs); 
580             vseg_id++) {
581            if (vseg[vseg_id].ident == 1) {
582                vseg_map(&vseg[vseg_id]); 
583            }
584        }
585 
586        for (size_t vseg_id = vspace[vspace_id].vseg_offset; 
587             vseg_id < (vspace[vspace_id].vseg_offset + vspace[vspace_id].vsegs); 
588             vseg_id++) {
589            if (vseg[vseg_id].ident == 0) {
590                vseg_map(&vseg[vseg_id]); 
591            }
592        }
593    } 
594} // end buildMap()
595
596
597
598// Local Variables:
599// tab-width: 4
600// c-basic-offset: 4
601// c-file-offsets:((innamespace . 0)(inline-open . 0))
602// indent-tabs-mode: nil
603// End:
604
605// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
606
Note: See TracBrowser for help on using the repository browser.