source: soft/giet_vm/memo/src/pseg.cpp @ 416

Last change on this file since 416 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: 10.8 KB
RevLine 
[163]1/* -*- c++ -*-
2 *
[238]3 * GIET_VM_LGPL_HEADER_BEGIN
[163]4 *
5 * This file is part of SoCLib, GNU LGPLv2.1.
6 *
7 * SoCLib 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 * SoCLib 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 SoCLib; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 * 02110-1301 USA
20 *
[238]21 * GIET_VM_LGPL_HEADER_END
[163]22 *
23 * Copyright (c) UPMC, Lip6, SoC
24 *         Mohamed Lamine Karaoui <Mohamed.Karaoui@lip6.fr>, 2012
25 */
26
27#include <algorithm>
28#include <string.h>
29#include <cassert>
30#include <cstring>
31#include <stdexcept>
32
33#include <iostream>
34#include <sstream>
35#include <iomanip>
36
[255]37#include <cstdio>
38
[163]39#include "pseg.h"
40#include "exception.h"
41
42
[255]43#define max(x, y) (((x) > (y)) ? (x) : (y))
44
45
[163]46/*
47 * VSeg
48 */
49
[238]50//////////////////////////////////////
[255]51const std::string & VSeg::name() const {
[163]52        return m_name;
53}
54
[238]55//////////////////////////////////////
[255]56const std::string & VSeg::file() const {
[163]57        return m_file;
58}
59
[238]60///////////////////////////
[255]61uintptr_t VSeg::vma() const {
[163]62        return m_vma;
63}
64
[238]65/////////////////////////
[255]66paddr_t VSeg::lma() const {
[163]67        return m_lma;
68}
69
[238]70///////////////////////////
[255]71size_t VSeg::length() const {
[163]72        return m_length;
73}
74
[238]75/////////////////////////
[255]76size_t VSeg::type() const {
[210]77        return m_type;
78}
79
[238]80/////////////////////////////////////////
[255]81void VSeg::print(std::ostream &o) const
[163]82{
83        o << std::hex << std::noshowbase
84      << "<Virtual segment from(vaddr): 0x" 
85      << std::setw (8) << std::setfill('0') 
86      << m_vma << ", to(paddr) 0x"
[238]87      << std::setw (16) << std::setfill('0') 
[163]88      << m_lma << ", size: 0x"
89      << std::setw (8) << std::setfill('0') 
[255]90          << m_length  << ",ident: " 
91          << (m_ident ? "yes" : "no") << ", in(file): "
92          << m_file << ", name: " << m_name << ">";
[163]93}
94
[238]95/////////////
[255]96VSeg::~VSeg() {}
[163]97
[238]98/////////////////////////////////////////
[255]99VSeg & VSeg::operator=(const VSeg & ref)
[163]100{
[255]101    if (&ref == this)
[163]102        return *this;
103
[255]104    m_name = ref.m_name;
[163]105    m_file = ref.m_file;
106    m_vma = ref.m_vma;
107    m_lma = ref.m_lma;
108    m_length = ref.m_length;
109    m_ident = ref.m_ident;
[255]110    return *this;
[163]111}
112
[238]113////////////
[163]114VSeg::VSeg()
115    : m_name("No Name"),
[255]116    m_file("Empty section"),
117    m_vma(0),
118    m_length(0),
119    m_loadable(false),
120    m_ident(0)
[163]121{
122}
123
[238]124////////////////////////////////////
125VSeg::VSeg(std::string&  binaryName, 
[255]126        std::string&  name, 
127        uintptr_t     vma, 
128        size_t        length, 
129        bool          loadable, 
130        bool          ident)
131: m_name(name),
132    m_file(binaryName),
133    m_vma(vma),
134    m_length(length),
135    m_loadable(loadable),
136    m_ident(ident)
[163]137{
138}
139
[238]140/////////////////////////////
[255]141VSeg::VSeg(const VSeg &ref):
142    m_name(ref.m_name),
143    m_file(ref.m_file),
144    m_vma(ref.m_vma),
145    m_length(ref.m_length),
146    m_loadable(ref.m_loadable),
147    m_ident(ref.m_ident)
[163]148{
149    (*this) = ref;
150}
151
152
153/*
154 * PSeg
155 */
[238]156
157/////////////////////////
[255]158paddr_t PSeg::lma() const {
159    return m_lma;
[163]160}
161
[238]162///////////////////////////
[255]163paddr_t PSeg::length() const {
164    return m_length;
[163]165}
166
[238]167/////////////////////////
[255]168size_t PSeg::type() const {
169    return m_type;
[210]170}
171
[238]172//////////////////////////////////////
[255]173const std::string & PSeg::name() const {
174    return m_name;
[163]175}
176
[238]177//////////////////////// initialisation used[][] ??? (AG)
[163]178void PSeg::check() const
179{
[210]180
[255]181    if (this->m_type == PSEG_TYPE_PERI)
[210]182        return;
183
184    std::vector<VSeg>::const_iterator it;
[238]185    size_t    size = m_vsegs.size();
186    paddr_t   used[size][2];          // lma, lma+length
[255]187    size_t    i, j, error = 0;
188
189    for (it = m_vsegs.begin(), i = 0; it < m_vsegs.end(); it++, i++)
[163]190    {
[238]191        paddr_t it_limit = (*it).lma() + (*it).length();
[255]192        for(j = 0; j < i; j++)
[163]193        {
[255]194            if (used[j][0] == (*it).lma()) //not the same lma ,
195                {
196                    error = 1;
197                }
198            if (used[j][1] == it_limit)  // and not the same limit
[163]199            {
200                error = 2;
201            }
[255]202            if ((used[j][0] < (*it).lma()) and ((*it).lma() < used[j][1])) // lma  within
[163]203            {
204                error = 3;
205            }
[255]206            if (((used[j][0] < it_limit) and (it_limit < used[j][1]))) // limit no within
[163]207            {
208                error = 4;
[210]209                std::cout << "base: " << std::hex << (*it).lma() << std::endl;
[163]210                std::cout << "limit: " << std::hex << it_limit << std::endl;
211                std::cout << "used[j][0]: " << std::hex << used[j][0] << std::endl;
212                std::cout << "used[j][1]: " << std::hex << used[j][1] << std::endl;
213            }
[255]214            if (error)
[163]215            {
216                std::ostringstream err;
[255]217                err << " Error" << error << ", ovelapping Buffers:" << std::endl
[163]218                    << *it << std::endl << m_vsegs[j] << std::endl; 
[173]219                throw exception::RunTimeError( err.str().c_str() );
[163]220            }
221
222        }
223        used[i][0] = (*it).lma();
224        used[i][1] = it_limit;
225    }
226}
227
228
[238]229/////////////////////////////////////////////////////////
[255]230paddr_t PSeg::align(paddr_t toAlign, unsigned alignPow2) {
[238]231    return ((toAlign + (1 << alignPow2) - 1 ) >> alignPow2) << alignPow2; 
[163]232}
233
[238]234//////////////////////////////////////////
[255]235paddr_t PSeg::pageAlign(paddr_t toAlign) {
[163]236    size_t pgs = pageSize();
237    size_t pageSizePow2 = __builtin_ctz(pgs);
[255]238
[238]239    return align(toAlign, pageSizePow2); 
[163]240}
241
242
243
[255]244////////////////////////////
245void PSeg::add(VSeg& vseg) {
246    std::vector<VSeg>::iterator it;
247    int nb_elems = m_vsegs.size();
248    int i = 0;
249    bool mapped = false;
250    paddr_t prev_base = m_lma;
251    paddr_t prev_length = 0x0;
252    paddr_t curr_base = 0x0;
253    paddr_t curr_length = 0x0;
254    paddr_t next_base = 0x0;
255    paddr_t next_length = 0x0;
[163]256
[255]257    const int alignment = max(vseg.m_align, __builtin_ctz(pageSize())); // 12
[163]258
[255]259    if (vseg.length() == 0) {
260        std::cout << "*** Error: Adding a vseg of size 0 (base " << vseg.vma() << ")" << std::endl;
261        exit(1);
262    }
[163]263
[255]264    if (nb_elems == 0) {
265        if (vseg.length() <= m_length) {
266            vseg.m_lma = m_lma;
267            m_vsegs.push_back(vseg);
268            return;
269        }
270        else {
271            std::cout << "*** Error: Not enough space to map first VSeg (base = "
272                      << std::hex << vseg.vma() << " - Size = " << vseg.length() << ")" << std::endl;
273            std::cout << "    PSeg too small! (base = " << m_lma << " - size = "
274                      << m_length << ")" << std::endl;
275            exit(1);
276        }
277    }
[163]278
[255]279    curr_base = m_vsegs[0].lma(); // Initialisation avant recherche du min
280    curr_length = m_vsegs[0].length();
281    for (it = m_vsegs.begin(); it != m_vsegs.end(); it++) {
282        if ((*it).lma() < curr_base) {
283            curr_base = (*it).lma();
284            curr_length = (*it).length();
285        }
286    }
[163]287
[255]288    while (i < nb_elems) {
289        if (align(prev_base + prev_length, alignment) + vseg.length() <= curr_base) {
290            vseg.m_lma = align(prev_base + prev_length, alignment);
291            mapped = true;
292            break;
293        }
294        else if (i < nb_elems - 1) {
295            // Searching for the vseg already mapped with lowest paddr > curr_base
296            next_base = 0;
297            bool found = false;
298            for (it = m_vsegs.begin(); it != m_vsegs.end(); it++) {
299                if ((!found || (*it).lma() < next_base) && (*it).lma() > curr_base) {
300                    found = true;
301                    next_base = (*it).lma();
302                    next_length = (*it).length();
303                }
304            }
305            assert(found);
[163]306
[255]307            prev_base = curr_base;
308            prev_length = curr_length;
[163]309
[255]310            curr_base = next_base;
311            curr_length = next_length;
312        }
313        else {
314            if (align(curr_base + curr_length, alignment) + vseg.length() <= m_lma + m_length) {
315                vseg.m_lma = align(curr_base + curr_length, alignment);
316                mapped = true;
317            }
318        }
319        i++;
320    }
[163]321
[255]322    if (!mapped) {
323        std::cout << "*** Error: Not enough space to map VSeg (base = " << std::hex << vseg.vma() << " - Size = " << vseg.length() << ")" << std::endl;
324        exit(1);
[163]325    }
326
[255]327    m_vsegs.push_back(vseg); 
[163]328}
329
[255]330
[238]331/////////////////////////////////
[255]332void PSeg::addIdent(VSeg& vseg) {
333    std::vector<VSeg>::iterator it;
334
335    for (it = m_vsegs.begin(); it != m_vsegs.end(); it++) {
336        if ((vseg.vma() == (*it).lma()) ||
337            ((vseg.vma() < (*it).lma()) && (vseg.vma() + vseg.length() > (*it).lma())) ||
338            ((vseg.vma() > (*it).lma()) && ((*it).lma() + (*it).length() > vseg.vma()))) {
339            std::cout << "*** Error: Identity VSeg overlaps another segment:" << std::endl
340                      << "Added Segment Base : " << std::hex << vseg.vma()
341                      << " - Size : " << vseg.length() << std::endl;
342            std::cout << "Existing Segment Base : " << (*it).lma()
343                      << " - size : " << (*it).length() << std::endl;
344            exit(1);
345        }
[163]346    }
347
[255]348    vseg.m_lma = vseg.m_vma;
349    m_vsegs.push_back(vseg); 
[163]350}
351
[255]352
[238]353/////////////////////////////////////////
[255]354PSeg & PSeg::operator=(const PSeg &ref) {
355    if (&ref == this) {
[163]356        return *this;
[255]357    }
[163]358
359    m_name = ref.m_name;
360    m_length = ref.m_length;
361    m_lma = ref.m_lma;
362    m_vsegs = ref.m_vsegs;
[227]363    m_type = ref.m_type;
[163]364
365        return *this;
366}
367
[238]368//////////////////////////////////////////
[255]369void PSeg::print(std::ostream &o) const
[163]370{
371        o << "<Physical segment "
372          << std::showbase << m_name
373          << ", from: " << std::hex
[255]374      << m_lma
[163]375      << ", size : "  << m_length
[227]376      << ", type : "  << m_type
[163]377      << ", containing: "<< std::endl;
378        std::vector<VSeg>::const_iterator it;
379        for(it = m_vsegs.begin(); it < m_vsegs.end(); it++)
380    o << " " << *it << std::endl;
381
382    o << ">";
383}
384
[238]385////////////////////////////////////
[163]386PSeg::PSeg( const std::string &name,
[238]387            paddr_t           lma,
388            paddr_t           length,
389            size_t            type)
[163]390{
391    m_name = name;
392    m_length = length;
[210]393    m_type = type;
[255]394    m_lma = lma;
[163]395}
396
[238]397////////////////////////////////////
[255]398PSeg::PSeg(const std::string &name):
[163]399      m_lma(0),
[255]400      m_length(0) {
[163]401    m_name = name;
402}
403
404
[255]405////////////////////////////////////
406PSeg::PSeg(const PSeg& pseg) {
407    m_name = pseg.m_name;
408    m_length = pseg.m_length;
409    m_lma = pseg.m_lma;
410    m_vsegs = pseg.m_vsegs;
411    m_type = pseg.m_type;
[163]412
[255]413    (*this) = pseg;
[163]414}
415
[255]416PSeg::~PSeg() {}
[163]417
418
419
420// Local Variables:
421// tab-width: 4
422// c-basic-offset: 4
423// c-file-offsets:((innamespace . 0)(inline-open . 0))
424// indent-tabs-mode: nil
425// End:
426
427// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
428
Note: See TracBrowser for help on using the repository browser.