source: soft/giet_vm/giet_common/vmem.c @ 758

Last change on this file since 758 was 758, checked in by alain, 8 years ago

We introduce the _v2p_add_pte1(), _v2p_add_pte2(),
_v2p_del_pte1(), _v2p_del_pte2() functions in the vmem.c file,
in order to support the mmap() and munmap() functions.

  • Property svn:executable set to *
File size: 11.8 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    // get PT1 physical base address
132    paddr_t  pt1_base = _ptabs_paddr[vspace_id][x][y];
133
134    if ( pt1_base == 0 )
135    {
136        _printf("\n[GIET ERROR] in _v2p_add_pte1() : no PTAB in cluster[%d,%d]"
137                    " containing processors\n", x , y );
138        _exit();
139    }
140
141    // get lock protecting PTAB[vspace_id][x][y]
142    _spin_lock_acquire( &_ptabs_spin_lock[vspace_id][x][y] );
143
144    // compute pte1 physical address
145    paddr = pt1_base + 4*ix1;
146
147    // check PTE1 not already mapped
148    if ( ident == 0 )
149    {
150        if ( _physical_read( paddr ) & PTE_V )
151        {
152            _printf("\n[GIET ERROR] in _v2p_add_pte1() : vpn %x already mapped "
153                    "in PTAB[%d,%d] for vspace %d\n", vpn , x , y , vspace_id );
154            _spin_lock_release( &_ptabs_spin_lock[vspace_id][x][y] );
155            _exit();
156        }
157    }
158
159    // compute pte1 : 2 bits V T / 8 bits flags / 3 bits RSVD / 19 bits bppi
160    pte1 = PTE_V | (flags & 0x3FC00000) | ((ppn>>9) & 0x0007FFFF);
161
162    // write pte1 in PT1
163    _physical_write( paddr , pte1 );
164
165    // release lock protecting PTAB[vspace_id][x][y]
166    _spin_lock_release( &_ptabs_spin_lock[vspace_id][x][y] );
167
168    asm volatile ("sync");
169
170}   // end _v2p_add_pte1()
171
172
173
174///////////////////////////////////////////
175void _v2p_add_pte2( unsigned int vspace_id,
176                    unsigned int x,
177                    unsigned int y,
178                    unsigned int vpn,        // 20 bits right-justified
179                    unsigned int flags,      // 10 bits left-justified
180                    unsigned int ppn,        // 28 bits right-justified
181                    unsigned int ident )     // identity mapping if non zero
182{
183    unsigned int ix1;
184    unsigned int ix2;
185    paddr_t      pt2_pbase;     // PT2 physical base address
186    paddr_t      pte2_paddr;    // PTE2 physical address
187    unsigned int pt2_id;        // PT2 index
188    unsigned int ptd;           // PTD : entry in PT1
189
190    ix1 = vpn >> 9;             // 11 bits for ix1
191    ix2 = vpn & 0x1FF;          //  9 bits for ix2
192
193#if GIET_DEBUG_VMEM
194if ( _get_proctime() > GIET_DEBUG_VMEM )
195_printf("\n@@@ _v2p_add_pte2() : enters for vpn = %x / ppn = %x / PTAB[%d,%d,%d]\n",
196        vpn , ppn , vspace_id , x , y );
197#endif
198
199    // get page table physical base address
200    paddr_t      pt1_pbase = _ptabs_paddr[vspace_id][x][y];
201
202    if ( pt1_pbase == 0 )
203    {
204        _printf("\n[GIET ERROR] in _v2p_add_pte2() : no PTAB for vspace %d "
205                "in cluster[%d,%d]\n", vspace_id , x , y );
206        _exit();
207    }
208
209    // get lock protecting PTAB[vspace_id][x][y]
210    _spin_lock_acquire( &_ptabs_spin_lock[vspace_id][x][y] );
211
212    // get ptd in PT1
213    ptd = _physical_read( pt1_pbase + 4 * ix1 );
214
215    if ((ptd & PTE_V) == 0)    // undefined PTD: compute PT2 base address,
216                               // and set a new PTD in PT1
217    {
218        // get a new pt2_id
219        pt2_id = _ptabs_next_pt2[vspace_id][x][y];
220        _ptabs_next_pt2[vspace_id][x][y] = pt2_id + 1;
221
222#if GIET_DEBUG_VMEM
223if ( _get_proctime() > GIET_DEBUG_VMEM )
224_printf("\n@@@ _v2p_add_pte2() new pt2_id = %d\n", pt2_id );
225#endif
226       
227        // check overflow
228        if (pt2_id == _ptabs_max_pt2) 
229        {
230            _printf("\n[GIET ERROR] in _v2p_add_pte2() : PTAB[%d,%d,%d]"
231                    " contains not enough PT2s\n", vspace_id, x, y );
232            _spin_lock_release( &_ptabs_spin_lock[vspace_id][x][y] );
233            _exit();
234        }
235
236        pt2_pbase = pt1_pbase + PT1_SIZE + PT2_SIZE * pt2_id;
237        ptd = PTE_V | PTE_T | (unsigned int) (pt2_pbase >> 12);
238
239        // set PTD into PT1
240        _physical_write( pt1_pbase + 4*ix1, ptd);
241
242#if GIET_DEBUG_VMEM
243if ( _get_proctime() > GIET_DEBUG_VMEM )
244_printf("\n@@@ _v2p_add_pte2() : &ptd = %l / ptd = %x\n", pt1_pbase + 4*ix1, ptd );
245#endif
246
247
248    }
249    else                       // valid PTD: compute PT2 base address
250    {
251        pt2_pbase = ((paddr_t)(ptd & 0x0FFFFFFF)) << 12;
252    }
253
254    // set PTE in PT2 : flags & PPN in two 32 bits words
255    pte2_paddr  = pt2_pbase + 8 * ix2;
256    _physical_write(pte2_paddr     , (PTE_V | flags) );
257    _physical_write(pte2_paddr + 4 , ppn );
258
259#if GIET_DEBUG_VMEM
260if ( _get_proctime() > GIET_DEBUG_VMEM )
261_printf("\n@@@ _v2p_add_pte2() : pt1_pbase = %l / pt2_pbase = %l" 
262        " / &pte2 = %l / ppn = %x / flags = %x\n",
263        pt1_pbase , pt2_pbase , pte2_paddr , ppn , PTE_V | flags );
264#endif
265
266    // release lock protecting PTAB[vspace_id][x][y]
267    _spin_lock_release( &_ptabs_spin_lock[vspace_id][x][y] );
268
269    asm volatile ("sync");
270
271}   // end _v2p_add_pte2()
272
273////////////////////////////////////////////
274void _v2p_del_pte1( unsigned int vspace_id,
275                    unsigned int x,
276                    unsigned int y,
277                    unsigned int vpn )       // 20 bits right-justified
278{
279    unsigned int ix1 = vpn >> 9;             // 11 bits for ix1
280
281    // get page table physical base address
282    paddr_t pt1_pbase = _ptabs_paddr[vspace_id][x][y];
283
284    // check PTAB defined
285    if ( pt1_pbase == 0 )
286    {
287        _printf("\n[GIET ERROR] in _v2p_del_pte1() : no PTAB for vspace %d "
288                "in cluster[%d,%d]\n", vspace_id , x , y );
289        _exit();
290    }
291
292    // get pte1 in PT1
293    paddr_t pte1_paddr = pt1_pbase + 4 * ix1;
294    unsigned int pte1 = _physical_read( pte1_paddr );
295
296    // check pte1 valid
297    if ((pte1 & PTE_V) == 0)   
298    {
299        _printf("\n[GIET ERROR] in _v2p_del_pte1() : vpn %x not mapped in PT1"
300                "for vspace %d in cluster[%d,%d]\n", vpn , vspace_id , x , y );
301        _exit();
302    }
303
304    // invalidate PTE1 in PT1
305    _physical_write( pte1_paddr , 0 );
306
307}   // end _v2p_del_pte1()
308 
309////////////////////////////////////////////
310void _v2p_del_pte2( unsigned int vspace_id,
311                    unsigned int x,
312                    unsigned int y,
313                    unsigned int vpn )       // 20 bits right-justified
314{
315    unsigned int ix1 = vpn >> 9;             // 11 bits for ix1
316    unsigned int ix2 = vpn & 0x1FF;          //  9 bits for ix2
317
318    // get page table physical base address
319    paddr_t pt1_pbase = _ptabs_paddr[vspace_id][x][y];
320
321    // check PTAB defined
322    if ( pt1_pbase == 0 )
323    {
324        _printf("\n[GIET ERROR] in _v2p_del_pte2() : no PTAB for vspace %d "
325                "in cluster[%d,%d]\n", vspace_id , x , y );
326        _exit();
327    }
328
329    // get ptd in PT1
330    unsigned int ptd = _physical_read( pt1_pbase + 4 * ix1 );
331
332    // check ptd valid
333    if ((ptd & PTE_V) == 0)   
334    {
335        _printf("\n[GIET ERROR] in _v2p_del_pte2() : vpn %x not mapped in PT1"
336                "for vspace %d in cluster[%d,%d]\n", vpn , vspace_id , x , y );
337        _exit();
338    }
339
340    // get PT2 physical base address
341    paddr_t  pt2_pbase = ((paddr_t)(ptd & 0x0FFFFFFF)) << 12;
342
343    // invalidate PTE in PT2
344    paddr_t pte2_paddr  = pt2_pbase + 8 * ix2;
345    _physical_write( pte2_paddr , 0 );
346
347    asm volatile ("sync");
348
349}  // end _v2p_del_pte2()
350
351
352
353// Local Variables:
354// tab-width: 4
355// c-basic-offset: 4
356// c-file-offsets:((innamespace . 0)(inline-open . 0))
357// indent-tabs-mode: nil
358// End:
359// vim: filetype=c:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
360
361
Note: See TracBrowser for help on using the repository browser.