source: soft/giet_vm/giet_common/vmem.c

Last change on this file was 791, checked in by meunier, 8 years ago
  • Added function realloc
  • Started to put the bootloader on 2 Big Pages (warning: does not work yet)
  • Fixed errors in the rosenfeld application
  • Property svn:executable set to *
File size: 11.9 KB
Line 
1///////////////////////////////////////////////////////////////////////////////////
2// File     : vmem.c
3// Date     : 01/07/2012
4// Author   : alain greiner
5// Copyright (c) UPMC-LIP6
6///////////////////////////////////////////////////////////////////////////////////
7
8#include <tty0.h>
9#include <utils.h>
10#include <vmem.h>
11#include <ctx_handler.h>
12#include <kernel_locks.h>
13#include <giet_config.h>
14
15//////////////////////////////////////////////////////////////////////////////////
16// Extern global variables (allocated in boot.c or kernel_init.c)
17//////////////////////////////////////////////////////////////////////////////////
18
19extern  spin_lock_t         _ptabs_spin_lock[GIET_NB_VSPACE_MAX][X_SIZE][Y_SIZE];
20extern  unsigned long long  _ptabs_paddr[GIET_NB_VSPACE_MAX][X_SIZE][Y_SIZE];
21extern  unsigned int        _ptabs_next_pt2[GIET_NB_VSPACE_MAX][X_SIZE][Y_SIZE];
22extern  unsigned int        _ptabs_max_pt2;
23
24///////////////////////////////////////////////////////
25unsigned long long _v2p_translate( unsigned int  vaddr,
26                                   unsigned int* flags )
27{
28    unsigned long long ptba;
29    unsigned long long pte2_paddr;
30
31    unsigned int pte2_msb;
32    unsigned int pte2_lsb;
33    unsigned int flags_value;
34    unsigned int ppn_value;
35
36    unsigned int save_sr;
37 
38    // decode the vaddr fields
39    unsigned int offset = vaddr & 0xFFF;
40    unsigned int ix1    = (vaddr >> 21) & 0x7FF;
41    unsigned int ix2    = (vaddr >> 12) & 0x1FF;
42
43    // get page table vbase address
44    page_table_t* pt = (page_table_t*)_get_context_slot(CTX_PTAB_ID);
45
46    // get PTE1
47    unsigned int pte1 = pt->pt1[ix1];
48
49    // check PTE1 mapping
50    if ( (pte1 & PTE_V) == 0 )
51    {
52        _printf("\n[VMEM ERROR] _v2p_translate() : pte1 unmapped\n"
53                "  vaddr = %x / ptab = %x / pte1_vaddr = %x / pte1_value = %x\n",
54                vaddr , (unsigned int)pt, &(pt->pt1[ix1]) , pte1 );
55        _exit();
56    }
57
58    // test big/small page
59    if ( (pte1 & PTE_T) == 0 )  // big page
60    {
61        *flags = pte1 & 0xFFC00000;
62        offset = offset | (ix2<<12);
63        return (((unsigned long long)(pte1 & 0x7FFFF)) << 21) | offset;
64    }
65    else                        // small page
66    {
67
68        // get physical addresses of pte2
69        ptba       = ((unsigned long long)(pte1 & 0x0FFFFFFF)) << 12;
70        pte2_paddr = ptba + 8*ix2;
71
72        // split physical address in two 32 bits words
73        pte2_lsb   = (unsigned int) pte2_paddr;
74        pte2_msb   = (unsigned int) (pte2_paddr >> 32);
75
76        // disable interrupts and save status register
77        _it_disable( &save_sr );
78
79        // get ppn_value and flags_value, using a physical read
80        // after temporary DTLB desactivation
81        asm volatile (
82                "mfc2    $2,     $1          \n"     /* $2 <= MMU_MODE       */
83                "andi    $3,     $2,    0xb  \n"
84                "mtc2    $3,     $1          \n"     /* DTLB off             */
85
86                "move    $4,     %3          \n"     /* $4 <= pte_lsb        */
87                "mtc2    %2,     $24         \n"     /* PADDR_EXT <= pte_msb */
88                "lw      %0,     0($4)       \n"     /* read flags           */ 
89                "lw      %1,     4($4)       \n"     /* read ppn             */
90                "mtc2    $0,     $24         \n"     /* PADDR_EXT <= 0       */
91
92                "mtc2    $2,     $1          \n"     /* restore MMU_MODE     */
93                : "=r" (flags_value), "=r" (ppn_value)
94                : "r"  (pte2_msb)   , "r"  (pte2_lsb)
95                : "$2", "$3", "$4" );
96
97        // restore saved status register
98        _it_restore( &save_sr );
99
100        // check PTE2 mapping
101        if ( (flags_value & PTE_V) == 0 )
102        {
103            _printf("\n[VMEM ERROR] _v2p_translate() : pte2 unmapped\n"
104                    "  vaddr = %x / ptab = %x / pte1_value = %x\n"
105                    "  pte2_paddr = %l / ppn = %x / flags = %x\n",
106                    vaddr , pt , pte1 , pte2_paddr ,  ppn_value , flags_value );
107            _exit();
108        }
109
110        *flags = flags_value & 0xFFC00000;
111        return (((unsigned long long)(ppn_value & 0x0FFFFFFF)) << 12) | offset;
112    }
113} // end _v2p_translate()
114
115
116////////////////////////////////////////////
117void _v2p_add_pte1( unsigned int vspace_id,
118                    unsigned int x,
119                    unsigned int y,
120                    unsigned int vpn,        // 20 bits right-justified
121                    unsigned int flags,      // 10 bits left-justified
122                    unsigned int ppn,        // 28 bits right-justified
123                    unsigned int ident )     // identity mapping if non zero
124{
125    unsigned int   pte1;     // PTE1 value
126    paddr_t        paddr;    // PTE1 physical address
127
128    // compute index in PT1
129    unsigned int    ix1 = vpn >> 9;         // 11 bits for ix1
130
131    //_printf("\n[GIET INFO] %s: mapping vaddr %x to paddr %l\n", __func__, (vpn << 12), (unsigned long long int) (ppn << 12));
132    // get PT1 physical base address
133    paddr_t  pt1_base = _ptabs_paddr[vspace_id][x][y];
134
135    if ( pt1_base == 0 )
136    {
137        _printf("\n[GIET ERROR] in _v2p_add_pte1() : no PTAB in cluster[%d,%d]"
138                    " containing processors\n", x , y );
139        _exit();
140    }
141
142    // get lock protecting PTAB[vspace_id][x][y]
143    _spin_lock_acquire( &_ptabs_spin_lock[vspace_id][x][y] );
144
145    // compute pte1 physical address
146    paddr = pt1_base + 4*ix1;
147
148    // check PTE1 not already mapped
149    if ( ident == 0 )
150    {
151        if ( _physical_read( paddr ) & PTE_V )
152        {
153            _printf("\n[GIET ERROR] in _v2p_add_pte1() : vpn %x already mapped "
154                    "in PTAB[%d,%d] for vspace %d\n", vpn , x , y , vspace_id );
155            _spin_lock_release( &_ptabs_spin_lock[vspace_id][x][y] );
156            _exit();
157        }
158    }
159
160    // compute pte1 : 2 bits V T / 8 bits flags / 3 bits RSVD / 19 bits bppi
161    pte1 = PTE_V | (flags & 0x3FC00000) | ((ppn>>9) & 0x0007FFFF);
162
163    // write pte1 in PT1
164    _physical_write( paddr , pte1 );
165
166    // release lock protecting PTAB[vspace_id][x][y]
167    _spin_lock_release( &_ptabs_spin_lock[vspace_id][x][y] );
168
169    asm volatile ("sync");
170
171}   // end _v2p_add_pte1()
172
173
174
175///////////////////////////////////////////
176void _v2p_add_pte2( unsigned int vspace_id,
177                    unsigned int x,
178                    unsigned int y,
179                    unsigned int vpn,        // 20 bits right-justified
180                    unsigned int flags,      // 10 bits left-justified
181                    unsigned int ppn,        // 28 bits right-justified
182                    unsigned int ident )     // identity mapping if non zero
183{
184    unsigned int ix1;
185    unsigned int ix2;
186    paddr_t      pt2_pbase;     // PT2 physical base address
187    paddr_t      pte2_paddr;    // PTE2 physical address
188    unsigned int pt2_id;        // PT2 index
189    unsigned int ptd;           // PTD : entry in PT1
190
191    ix1 = vpn >> 9;             // 11 bits for ix1
192    ix2 = vpn & 0x1FF;          //  9 bits for ix2
193
194#if GIET_DEBUG_VMEM
195if ( _get_proctime() > GIET_DEBUG_VMEM )
196_printf("\n@@@ _v2p_add_pte2() : enters for vpn = %x / ppn = %x / PTAB[%d,%d,%d]\n",
197        vpn , ppn , vspace_id , x , y );
198#endif
199
200    // get page table physical base address
201    paddr_t      pt1_pbase = _ptabs_paddr[vspace_id][x][y];
202
203    if ( pt1_pbase == 0 )
204    {
205        _printf("\n[GIET ERROR] in _v2p_add_pte2() : no PTAB for vspace %d "
206                "in cluster[%d,%d]\n", vspace_id , x , y );
207        _exit();
208    }
209
210    // get lock protecting PTAB[vspace_id][x][y]
211    _spin_lock_acquire( &_ptabs_spin_lock[vspace_id][x][y] );
212
213    // get ptd in PT1
214    ptd = _physical_read( pt1_pbase + 4 * ix1 );
215
216    if ((ptd & PTE_V) == 0)    // undefined PTD: compute PT2 base address,
217                               // and set a new PTD in PT1
218    {
219        // get a new pt2_id
220        pt2_id = _ptabs_next_pt2[vspace_id][x][y];
221        _ptabs_next_pt2[vspace_id][x][y] = pt2_id + 1;
222
223#if GIET_DEBUG_VMEM
224if ( _get_proctime() > GIET_DEBUG_VMEM )
225_printf("\n@@@ _v2p_add_pte2() new pt2_id = %d\n", pt2_id );
226#endif
227       
228        // check overflow
229        if (pt2_id == _ptabs_max_pt2) 
230        {
231            _printf("\n[GIET ERROR] in _v2p_add_pte2() : PTAB[%d,%d,%d]"
232                    " contains not enough PT2s\n", vspace_id, x, y );
233            _spin_lock_release( &_ptabs_spin_lock[vspace_id][x][y] );
234            _exit();
235        }
236
237        pt2_pbase = pt1_pbase + PT1_SIZE + PT2_SIZE * pt2_id;
238        ptd = PTE_V | PTE_T | (unsigned int) (pt2_pbase >> 12);
239
240        // set PTD into PT1
241        _physical_write( pt1_pbase + 4*ix1, ptd);
242
243#if GIET_DEBUG_VMEM
244if ( _get_proctime() > GIET_DEBUG_VMEM )
245_printf("\n@@@ _v2p_add_pte2() : &ptd = %l / ptd = %x\n", pt1_pbase + 4*ix1, ptd );
246#endif
247
248
249    }
250    else                       // valid PTD: compute PT2 base address
251    {
252        pt2_pbase = ((paddr_t)(ptd & 0x0FFFFFFF)) << 12;
253    }
254
255    // set PTE in PT2 : flags & PPN in two 32 bits words
256    pte2_paddr  = pt2_pbase + 8 * ix2;
257    _physical_write(pte2_paddr     , (PTE_V | flags) );
258    _physical_write(pte2_paddr + 4 , ppn );
259
260#if GIET_DEBUG_VMEM
261if ( _get_proctime() > GIET_DEBUG_VMEM )
262_printf("\n@@@ _v2p_add_pte2() : pt1_pbase = %l / pt2_pbase = %l" 
263        " / &pte2 = %l / ppn = %x / flags = %x\n",
264        pt1_pbase , pt2_pbase , pte2_paddr , ppn , PTE_V | flags );
265#endif
266
267    // release lock protecting PTAB[vspace_id][x][y]
268    _spin_lock_release( &_ptabs_spin_lock[vspace_id][x][y] );
269
270    asm volatile ("sync");
271
272}   // end _v2p_add_pte2()
273
274////////////////////////////////////////////
275void _v2p_del_pte1( unsigned int vspace_id,
276                    unsigned int x,
277                    unsigned int y,
278                    unsigned int vpn )       // 20 bits right-justified
279{
280    unsigned int ix1 = vpn >> 9;             // 11 bits for ix1
281
282    // get page table physical base address
283    paddr_t pt1_pbase = _ptabs_paddr[vspace_id][x][y];
284
285    // check PTAB defined
286    if ( pt1_pbase == 0 )
287    {
288        _printf("\n[GIET ERROR] in _v2p_del_pte1() : no PTAB for vspace %d "
289                "in cluster[%d,%d]\n", vspace_id , x , y );
290        _exit();
291    }
292
293    // get pte1 in PT1
294    paddr_t pte1_paddr = pt1_pbase + 4 * ix1;
295    unsigned int pte1 = _physical_read( pte1_paddr );
296
297    // check pte1 valid
298    if ((pte1 & PTE_V) == 0)   
299    {
300        _printf("\n[GIET ERROR] in _v2p_del_pte1() : vpn %x not mapped in PT1"
301                "for vspace %d in cluster[%d,%d]\n", vpn , vspace_id , x , y );
302        _exit();
303    }
304
305    // invalidate PTE1 in PT1
306    _physical_write( pte1_paddr , 0 );
307
308}   // end _v2p_del_pte1()
309 
310////////////////////////////////////////////
311void _v2p_del_pte2( unsigned int vspace_id,
312                    unsigned int x,
313                    unsigned int y,
314                    unsigned int vpn )       // 20 bits right-justified
315{
316    unsigned int ix1 = vpn >> 9;             // 11 bits for ix1
317    unsigned int ix2 = vpn & 0x1FF;          //  9 bits for ix2
318
319    // get page table physical base address
320    paddr_t pt1_pbase = _ptabs_paddr[vspace_id][x][y];
321
322    // check PTAB defined
323    if ( pt1_pbase == 0 )
324    {
325        _printf("\n[GIET ERROR] in _v2p_del_pte2() : no PTAB for vspace %d "
326                "in cluster[%d,%d]\n", vspace_id , x , y );
327        _exit();
328    }
329
330    // get ptd in PT1
331    unsigned int ptd = _physical_read( pt1_pbase + 4 * ix1 );
332
333    // check ptd valid
334    if ((ptd & PTE_V) == 0)   
335    {
336        _printf("\n[GIET ERROR] in _v2p_del_pte2() : vpn %x not mapped in PT1"
337                "for vspace %d in cluster[%d,%d]\n", vpn , vspace_id , x , y );
338        _exit();
339    }
340
341    // get PT2 physical base address
342    paddr_t  pt2_pbase = ((paddr_t)(ptd & 0x0FFFFFFF)) << 12;
343
344    // invalidate PTE in PT2
345    paddr_t pte2_paddr  = pt2_pbase + 8 * ix2;
346    _physical_write( pte2_paddr , 0 );
347
348    asm volatile ("sync");
349
350}  // end _v2p_del_pte2()
351
352
353
354// Local Variables:
355// tab-width: 4
356// c-basic-offset: 4
357// c-file-offsets:((innamespace . 0)(inline-open . 0))
358// indent-tabs-mode: nil
359// End:
360// vim: filetype=c:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
361
362
Note: See TracBrowser for help on using the repository browser.