source: trunk/hal/tsar_mips32/core/hal_vmm.c

Last change on this file was 656, checked in by alain, 11 months ago

Fix several bugs in the FATFS and in the VFS,
related to the creation of big files requiring
more than 4 Kbytes (one cluster) on device.

File size: 11.7 KB
Line 
1/*
2 * hal_vmm.c - Virtual Memory Manager Initialisation for TSAR
3 *
4 * Authors  Alain Greiner (2016,2017,2018,2019)
5 *
6 * Copyright (c) UPMC Sorbonne Universites
7 *
8 * This file is part of ALMOS-MKH.
9 *
10 * ALMOS-MKH is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; version 2.0 of the License.
13 *
14 * ALMOS-MKH is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17 * General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with ALMOS-MKH; if not, write to the Free Software Foundation,
21 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22 */
23
24#include <kernel_config.h>
25#include <hal_kernel_types.h>
26#include <hal_vmm.h>
27#include <hal_gpt.h>
28#include <process.h>
29#include <thread.h>
30#include <vseg.h>
31#include <xlist.h>
32#include <vmm.h>
33#include <remote_rwlock.h>
34
35//////////////////////////////////////////////////////////////////////////////////////////
36// This file contains the TSAR specific code used to initialize the kernel process VMM,
37// or to update an user process VMM with informations related to the kernel vsegs.
38// As the TSAR architure does not use the DATA MMU, but use only the DATA extension
39// address register to access local and remote kernel data, the kernel VSL contains only
40// one "kcode" segment, and the kernel GPT contains only one big page in PT1[0] slot.
41//////////////////////////////////////////////////////////////////////////////////////////
42
43// extern global variables
44extern process_t            process_zero;
45extern chdev_directory_t    chdev_dir;
46extern char               * lock_type_str[];
47
48//////////////////////////////////////////////////////////////////////////////////////////
49// This function is called by the process_zero_init() function during kernel_init.
50// It initializes the VMM of the kernel proces_zero (containing all kernel threads)
51// in the local cluster.
52// For TSAR, it registers one "kcode" vseg in kernel VSL, and registers one big page
53// in slot[0] of kernel GPT.
54//////////////////////////////////////////////////////////////////////////////////////////
55error_t  hal_vmm_kernel_init( boot_info_t * info )
56{
57    error_t   error;
58
59    // get pointer on kernel GPT
60    gpt_t * gpt = &process_zero.vmm.gpt;
61
62#if DEBUG_HAL_VMM
63thread_t * this = CURRENT_THREAD;
64printk("\n[%s] thread[%x,%x] enter in cluster %x\n", 
65__FUNCTION__, this->process->pid, this->trdid, local_cxy );
66#endif
67
68    // allocate memory for kernel GPT
69    error = hal_gpt_create( gpt );
70
71    if( error )
72    {
73        printk("\n[PANIC] in %s : cannot allocate kernel GPT in cluster %x\n",
74        __FUNCTION__ , local_cxy );
75        hal_core_sleep();
76    }
77
78#if DEBUG_HAL_VMM
79printk("\n[%s] thread[%x,%x] created GPT PT1 in cluster %x / gpt %x\n", 
80__FUNCTION__, this->process->pid, this->trdid, local_cxy, gpt );
81#endif
82
83    // compute attr and ppn for one PTE1
84    uint32_t attr = GPT_MAPPED | GPT_READABLE | GPT_CACHABLE | GPT_EXECUTABLE | GPT_GLOBAL;
85    uint32_t ppn  = local_cxy << 20;   
86
87    // set PT1[0]
88    hal_gpt_set_pte( XPTR( local_cxy , gpt ) , 0 , attr , ppn );
89
90#if DEBUG_HAL_VMM
91printk("\n[%s] thread[%x,%x] mapped PT1[0] in cluster %d : ppn %x / attr %x\n", 
92__FUNCTION__, this->process->pid, this->trdid, local_cxy, ppn, attr );
93#endif
94
95    // create kcode vseg and register it in kernel VSL
96    vseg_t * vseg = vmm_create_vseg( &process_zero,
97                                     VSEG_TYPE_KCODE,
98                                     info->kcode_base,
99                                     info->kcode_size,
100                                     0, 0,               // file ofset and file size (unused)
101                                     XPTR_NULL,          // no mapper
102                                     local_cxy );
103    if( vseg == NULL )
104    {
105        printk("\n[PANIC] in %s : cannot register vseg to VSL in cluster %x\n",
106        __FUNCTION__ , local_cxy );
107        hal_core_sleep();
108    }
109
110#if DEBUG_HAL_VMM
111printk("\n[%s] thread[%x,%x] registered kcode vseg[%x,%x] in cluster %x\n",
112__FUNCTION__, this->process->pid, this->trdid, info->kcode_base, info->kcode_size, local_cxy );
113hal_vmm_display( XPTR( local_cxy, &process_zero ) , true );
114#endif
115
116    return 0;
117
118}  // end hal_vmm_kernel_init()
119
120//////////////////////////////////////////////////////////////////////////////////////////
121// This function registers in the VMM of an user process identified by the <process>
122// argument all required kernel vsegs.
123// For TSAR, it registers in the user VSL the "kcode" vseg, from the local kernel VSL,
124// and register in the user GPT the big page[0] from the local kernel GPT.
125//////////////////////////////////////////////////////////////////////////////////////////
126error_t hal_vmm_kernel_update( process_t * process )
127{
128    uint32_t attr;
129    uint32_t ppn;
130
131    // get cluster identifier
132    cxy_t cxy = local_cxy;
133
134#if DEBUG_HAL_VMM
135thread_t * this = CURRENT_THREAD;
136printk("\n[%s] thread[%x,%x] enter in cluster %x \n", 
137__FUNCTION__, this->process->pid, this->trdid, cxy );
138hal_vmm_display( XPTR( local_cxy , process ) , true );
139#endif
140
141    // get extended pointer on local kernel GPT
142    xptr_t k_gpt_xp = XPTR( cxy , &process_zero.vmm.gpt );
143
144    // get ppn and attributes from slot[0] of kernel GPT
145    hal_gpt_get_pte( k_gpt_xp , 0 , &attr , &ppn );
146
147#if DEBUG_HAL_VMM
148printk("\n[%s] thread[%x,%x] get PT1[0] ( ppn %x / attr %x ) from kernel  GPT\n", 
149__FUNCTION__, this->process->pid, this->trdid, ppn, attr );
150#endif
151
152    // get extended pointer on user GPT
153    xptr_t u_gpt_xp = XPTR( cxy , &process->vmm.gpt );
154
155    // update user GPT : set PTE1 in slot[0]
156    hal_gpt_set_pte( u_gpt_xp , 0 , attr , ppn );
157
158#if DEBUG_HAL_VMM
159printk("\n[%s] thread[%x,%x] registered PT1[0] ( ppn %x / attr %x ) to user GPT\n", 
160__FUNCTION__, this->process->pid, this->trdid, ppn, attr );
161#endif
162
163    // get pointer on the unique vseg registered in kernel VSL
164    xptr_t   root_xp = XPTR( cxy , &process_zero.vmm.vsegs_root );
165    xptr_t   vseg_xp = XLIST_FIRST( root_xp , vseg_t , xlist );
166    vseg_t * vseg    = GET_PTR( vseg_xp );
167
168// check vsegs_nr
169assert( (process_zero.vmm.vsegs_nr == 1 ) ,
170"bad vsegs number in kernel VSL = %d\n", process_zero.vmm.vsegs_nr );
171
172    // update user VSL : register one new vseg for kcode
173    vseg_t * new = vmm_create_vseg( process,
174                                    vseg->type,
175                                    vseg->min,
176                                    vseg->max - vseg->min,
177                                    0, 0,          // file ofset and file size (unused)
178                                    XPTR_NULL,     // no mapper
179                                    local_cxy );
180    if( new == NULL )
181    {
182        printk("\n[ERROR] in %s : cannot update user VSL in cluster %x\n",
183        __FUNCTION__ , cxy );
184        return -1;
185    }
186
187#if DEBUG_HAL_VMM
188printk("\n[%s] thread[%x,%x] created vseg %s ( base %x / size %x ) to user VSL\n", 
189__FUNCTION__, this->process->pid, this->trdid,
190vseg_type_str(vseg->type) , vseg->min, (vseg->max - vseg->min) );
191hal_vmm_display( XPTR( local_cxy , process ) , true );
192#endif
193
194    return 0;
195
196}  // end hal_vmm_kernel_update()
197
198//////////////////////////////////////////
199void hal_vmm_display( xptr_t   process_xp,
200                      bool_t   mapping )
201{
202    // get target process cluster and local pointer
203    process_t * process_ptr = GET_PTR( process_xp );
204    cxy_t       process_cxy = GET_CXY( process_xp );
205
206    // get local pointer on target process VMM
207    vmm_t * vmm = &process_ptr->vmm;
208
209    // get pointers on TXT0 chdev
210    xptr_t    txt0_xp  = chdev_dir.txt_tx[0];
211    cxy_t     txt0_cxy = GET_CXY( txt0_xp );
212    chdev_t * txt0_ptr = GET_PTR( txt0_xp );
213
214    // build extended pointer on TXT0 lock
215    xptr_t  txt_lock_xp = XPTR( txt0_cxy  , &txt0_ptr->wait_lock );
216
217    // build extended pointers on VSL lock and VSL root
218    xptr_t vsl_root_xp = XPTR( process_cxy , &vmm->vsegs_root );
219    xptr_t vsl_lock_xp = XPTR( process_cxy , &vmm->vsl_lock );
220
221    // get the locks protecting TXT0 and VSL
222    remote_queuelock_acquire( vsl_lock_xp );
223    remote_busylock_acquire( txt_lock_xp );
224
225    // get PID and PT1 values
226    pid_t      pid = hal_remote_l32( XPTR( process_cxy , &process_ptr->pid ) );
227    uint32_t * pt1 = hal_remote_lpt( XPTR( process_cxy , &vmm->gpt.ptr ) );
228
229    nolock_printk("\n***** VSL and GPT / process %x / cluster %x / PT1 %x / cycle %d\n",
230    pid , process_cxy , pt1 , (uint32_t)hal_get_cycles() );
231
232    if( xlist_is_empty( vsl_root_xp ) )
233    {
234        nolock_printk("   ... no vsegs registered\n");
235    }
236    else  // scan the list of vsegs
237    {
238        xptr_t         iter_xp;
239        xptr_t         vseg_xp;
240        vseg_t       * vseg_ptr;
241        cxy_t          vseg_cxy;
242        intptr_t       min;
243        intptr_t       max;
244        uint32_t       type;
245        intptr_t       vpn_base;
246        intptr_t       vpn_size;
247
248        XLIST_FOREACH( vsl_root_xp , iter_xp )
249        {
250            vseg_xp  = XLIST_ELEMENT( iter_xp , vseg_t , xlist );
251            vseg_ptr = GET_PTR( vseg_xp );
252            vseg_cxy = GET_CXY( vseg_xp );
253
254            type     =           hal_remote_l32( XPTR( vseg_cxy , &vseg_ptr->type ) );
255            min      = (intptr_t)hal_remote_lpt( XPTR( vseg_cxy , &vseg_ptr->min ) );
256            max      = (intptr_t)hal_remote_lpt( XPTR( vseg_cxy , &vseg_ptr->max ) );
257            vpn_size = (intptr_t)hal_remote_lpt( XPTR( vseg_cxy , &vseg_ptr->vpn_size ) );
258            vpn_base = (intptr_t)hal_remote_lpt( XPTR( vseg_cxy , &vseg_ptr->vpn_base ) );
259
260            nolock_printk(" - %s : base = %X / size = %X / npages = %d\n",
261            vseg_type_str(type), min, max - min, vpn_size );
262
263            if( mapping ) 
264            {
265                vpn_t    vpn     = vpn_base;
266                vpn_t    vpn_max = vpn_base + vpn_size;
267                ppn_t    ppn;
268                uint32_t attr;
269
270                while( vpn < vpn_max )   // scan the PTEs
271                {
272                    hal_gpt_get_pte( XPTR( process_cxy , &vmm->gpt ) , vpn , &attr , &ppn );
273
274                    if( attr & GPT_MAPPED )
275                    {
276                        if( attr & GPT_SMALL )
277                        {
278                            nolock_printk("    . SMALL : vpn = %X / attr = %X / ppn = %X\n",
279                            vpn , attr , ppn );
280                            vpn++;
281                        }
282                        else
283                        {
284                            nolock_printk("    . BIG   : vpn = %X / attr = %X / ppn = %X\n",
285                            vpn , attr , ppn );
286                            vpn += 512;
287                        }
288                    }
289                    else
290                    {
291                        vpn++;
292                    }
293                }
294            }
295        }
296    }
297
298#if CONFIG_INSTRUMENTATION_GPT
299uint32_t pte1_events = hal_remote_l32( XPTR( process_cxy , &vmm->gpt.pte1_wait_events ) );
300uint32_t pte1_iters  = hal_remote_l32( XPTR( process_cxy , &vmm->gpt.pte1_wait_iters ) );
301uint32_t pte1_ratio  = (pte1_events == 0 ) ? 0 : (pte1_iters / pte1_events);
302nolock_printk("\nGPT_WAIT_PTE1 : %d events / %d iterations => %d iter/event\n",
303pte1_events, pte1_iters, pte1_ratio );
304
305uint32_t pte2_events = hal_remote_l32( XPTR( process_cxy , &vmm->gpt.pte1_wait_events ) );
306uint32_t pte2_iters  = hal_remote_l32( XPTR( process_cxy , &vmm->gpt.pte1_wait_iters ) );
307uint32_t pte2_ratio  = (pte2_events == 0 ) ? 0 : (pte2_iters / pte2_events);
308nolock_printk("GPT_WAIT_PTE2 : %d events / %d iterations => %d iter/event\n",
309pte2_events, pte2_iters, pte2_ratio );
310#endif
311
312    // release locks
313    remote_busylock_release( txt_lock_xp );
314    remote_queuelock_release( vsl_lock_xp );
315
316}  // hal_vmm_display()
317
318
Note: See TracBrowser for help on using the repository browser.