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

Last change on this file since 358 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
Line 
1/* -*- c++ -*-
2 *
3 * GIET_VM_LGPL_HEADER_BEGIN
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 *
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 <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
37#include <cstdio>
38
39#include "pseg.h"
40#include "exception.h"
41
42
43#define max(x, y) (((x) > (y)) ? (x) : (y))
44
45
46/*
47 * VSeg
48 */
49
50//////////////////////////////////////
51const std::string & VSeg::name() const {
52        return m_name;
53}
54
55//////////////////////////////////////
56const std::string & VSeg::file() const {
57        return m_file;
58}
59
60///////////////////////////
61uintptr_t VSeg::vma() const {
62        return m_vma;
63}
64
65/////////////////////////
66paddr_t VSeg::lma() const {
67        return m_lma;
68}
69
70///////////////////////////
71size_t VSeg::length() const {
72        return m_length;
73}
74
75/////////////////////////
76size_t VSeg::type() const {
77        return m_type;
78}
79
80/////////////////////////////////////////
81void VSeg::print(std::ostream &o) const
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"
87      << std::setw (16) << std::setfill('0') 
88      << m_lma << ", size: 0x"
89      << std::setw (8) << std::setfill('0') 
90          << m_length  << ",ident: " 
91          << (m_ident ? "yes" : "no") << ", in(file): "
92          << m_file << ", name: " << m_name << ">";
93}
94
95/////////////
96VSeg::~VSeg() {}
97
98/////////////////////////////////////////
99VSeg & VSeg::operator=(const VSeg & ref)
100{
101    if (&ref == this)
102        return *this;
103
104    m_name = ref.m_name;
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;
110    return *this;
111}
112
113////////////
114VSeg::VSeg()
115    : m_name("No Name"),
116    m_file("Empty section"),
117    m_vma(0),
118    m_length(0),
119    m_loadable(false),
120    m_ident(0)
121{
122}
123
124////////////////////////////////////
125VSeg::VSeg(std::string&  binaryName, 
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)
137{
138}
139
140/////////////////////////////
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)
148{
149    (*this) = ref;
150}
151
152
153/*
154 * PSeg
155 */
156
157/////////////////////////
158paddr_t PSeg::lma() const {
159    return m_lma;
160}
161
162///////////////////////////
163paddr_t PSeg::length() const {
164    return m_length;
165}
166
167/////////////////////////
168size_t PSeg::type() const {
169    return m_type;
170}
171
172//////////////////////////////////////
173const std::string & PSeg::name() const {
174    return m_name;
175}
176
177//////////////////////// initialisation used[][] ??? (AG)
178void PSeg::check() const
179{
180
181    if (this->m_type == PSEG_TYPE_PERI)
182        return;
183
184    std::vector<VSeg>::const_iterator it;
185    size_t    size = m_vsegs.size();
186    paddr_t   used[size][2];          // lma, lma+length
187    size_t    i, j, error = 0;
188
189    for (it = m_vsegs.begin(), i = 0; it < m_vsegs.end(); it++, i++)
190    {
191        paddr_t it_limit = (*it).lma() + (*it).length();
192        for(j = 0; j < i; j++)
193        {
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
199            {
200                error = 2;
201            }
202            if ((used[j][0] < (*it).lma()) and ((*it).lma() < used[j][1])) // lma  within
203            {
204                error = 3;
205            }
206            if (((used[j][0] < it_limit) and (it_limit < used[j][1]))) // limit no within
207            {
208                error = 4;
209                std::cout << "base: " << std::hex << (*it).lma() << std::endl;
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            }
214            if (error)
215            {
216                std::ostringstream err;
217                err << " Error" << error << ", ovelapping Buffers:" << std::endl
218                    << *it << std::endl << m_vsegs[j] << std::endl; 
219                throw exception::RunTimeError( err.str().c_str() );
220            }
221
222        }
223        used[i][0] = (*it).lma();
224        used[i][1] = it_limit;
225    }
226}
227
228
229/////////////////////////////////////////////////////////
230paddr_t PSeg::align(paddr_t toAlign, unsigned alignPow2) {
231    return ((toAlign + (1 << alignPow2) - 1 ) >> alignPow2) << alignPow2; 
232}
233
234//////////////////////////////////////////
235paddr_t PSeg::pageAlign(paddr_t toAlign) {
236    size_t pgs = pageSize();
237    size_t pageSizePow2 = __builtin_ctz(pgs);
238
239    return align(toAlign, pageSizePow2); 
240}
241
242
243
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;
256
257    const int alignment = max(vseg.m_align, __builtin_ctz(pageSize())); // 12
258
259    if (vseg.length() == 0) {
260        std::cout << "*** Error: Adding a vseg of size 0 (base " << vseg.vma() << ")" << std::endl;
261        exit(1);
262    }
263
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    }
278
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    }
287
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);
306
307            prev_base = curr_base;
308            prev_length = curr_length;
309
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    }
321
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);
325    }
326
327    m_vsegs.push_back(vseg); 
328}
329
330
331/////////////////////////////////
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        }
346    }
347
348    vseg.m_lma = vseg.m_vma;
349    m_vsegs.push_back(vseg); 
350}
351
352
353/////////////////////////////////////////
354PSeg & PSeg::operator=(const PSeg &ref) {
355    if (&ref == this) {
356        return *this;
357    }
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;
363    m_type = ref.m_type;
364
365        return *this;
366}
367
368//////////////////////////////////////////
369void PSeg::print(std::ostream &o) const
370{
371        o << "<Physical segment "
372          << std::showbase << m_name
373          << ", from: " << std::hex
374      << m_lma
375      << ", size : "  << m_length
376      << ", type : "  << m_type
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
385////////////////////////////////////
386PSeg::PSeg( const std::string &name,
387            paddr_t           lma,
388            paddr_t           length,
389            size_t            type)
390{
391    m_name = name;
392    m_length = length;
393    m_type = type;
394    m_lma = lma;
395}
396
397////////////////////////////////////
398PSeg::PSeg(const std::string &name):
399      m_lma(0),
400      m_length(0) {
401    m_name = name;
402}
403
404
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;
412
413    (*this) = pseg;
414}
415
416PSeg::~PSeg() {}
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.