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

Last change on this file since 624 was 624, checked in by alain, 3 years ago

Fix several bugs to use the instruction MMU in kernel mode
in replacement of the instruction address extension register,
and remove the "kentry" segment.

This version is running on the tsar_generic_iob" platform.

One interesting bug: the cp0_ebase defining the kernel entry point
(for interrupts, exceptions and syscalls) must be initialized
early in kernel_init(), because the VFS initialisation done by
kernel_ini() uses RPCs, and RPCs uses Inter-Processor-Interrup.

File size: 9.9 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;
46
47//////////////////////////////////////////////////////////////////////////////////////////
48// This function is called by the process_zero_init() function during kernel_init.
49// It initializes the VMM of the kernel proces_zero (containing all kernel threads)
50// in the local cluster: it registers one "kcode" vseg in kernel VSL, and registers
51// one big page in slot[0] of kernel GPT.
52//////////////////////////////////////////////////////////////////////////////////////////
53error_t  hal_vmm_kernel_init( boot_info_t * info )
54{
55    error_t   error;
56
57    // get pointer on kernel GPT
58    gpt_t * gpt = &process_zero.vmm.gpt;
59
60    // get cluster identifier
61    cxy_t cxy = local_cxy;
62
63    // allocate memory for kernel GPT
64    error = hal_gpt_create( gpt );
65
66    if( error )
67    {
68        printk("\n[PANIC] in %s : cannot allocate kernel GPT in cluster %x\n",
69        __FUNCTION__ , cxy );
70        hal_core_sleep();
71    }
72
73#if DEBUG_HAL_VMM
74thread_t * this = CURRENT_THREAD;
75printk("\n[%s] thread[%x,%x] enter in cluster %x / gpt %x\n", 
76__FUNCTION__, this->process->pid, this->trdid, local_cxy, gpt );
77#endif
78
79    // compute attr and ppn for one PTE1
80    uint32_t attr = GPT_MAPPED | GPT_READABLE | GPT_CACHABLE | GPT_EXECUTABLE | GPT_GLOBAL;
81    uint32_t ppn  = cxy << 20;   
82
83    // register PTE1  in slot[0] of kernel GPT
84    error = hal_gpt_set_pte( XPTR( cxy , gpt ) , 0 , attr , ppn );
85
86    if( error )
87    {
88        printk("\n[PANIC] in %s : cannot initialize kernel GPT in cluster %x\n",
89        __FUNCTION__ , cxy );
90        hal_core_sleep();
91    }
92
93#if DEBUG_HAL_VMM
94printk("\n[%s] thread[%x,%x] created PT1[0] : ppn %x / attr %x\n", 
95__FUNCTION__, this->process->pid, this->trdid, ppn, attr );
96#endif
97
98    // create kcode vseg and register it in kernel VSL
99    vseg_t * vseg = vmm_create_vseg( &process_zero,
100                                     VSEG_TYPE_KCODE,
101                                     info->kcode_base,
102                                     info->kcode_size,
103                                     0, 0,                  // file ofset and file size (unused)
104                                     XPTR_NULL,             // no mapper
105                                     local_cxy );
106    if( vseg == NULL )
107    {
108        printk("\n[PANIC] in %s : cannot register vseg to VSL in cluster %x\n",
109        __FUNCTION__ , cxy );
110        hal_core_sleep();
111    }
112
113#if DEBUG_HAL_VMM
114printk("\n[%s] thread[%x,%x] registered kcode vseg[%x,%x]\n",
115__FUNCTION__, this->process->pid, this->trdid, info->kcode_base, info->kcode_size );
116hal_vmm_display( &process_zero , true );
117#endif
118
119    return 0;
120
121}  // end hal_kernel_vmm_init()
122
123//////////////////////////////////////////////////////////////////////////////////////////
124// This function is called by the vmm_init() function to update the VMM of an user
125// process identified by the <process> argument.
126// It registers in the user VSL the "kcode" vseg, registered in the local kernel VSL,
127// and register in the user GPT the big page[0] mapped in the local kernel GPT.
128//////////////////////////////////////////////////////////////////////////////////////////
129error_t hal_vmm_kernel_update( process_t * process )
130{
131    error_t error;
132    uint32_t attr;
133    uint32_t ppn;
134
135#if DEBUG_HAL_VMM
136thread_t * this = CURRENT_THREAD;
137printk("\n[%s] thread[%x,%x] enter in cluster %x \n", 
138__FUNCTION__, this->process->pid, this->trdid, local_cxy );
139hal_vmm_display( process , true );
140hal_vmm_display( &process_zero , true );
141#endif
142
143    // get cluster identifier
144    cxy_t cxy = local_cxy;
145
146    // get extended pointer on kernel GPT
147    xptr_t k_gpt_xp = XPTR( cxy , &process_zero.vmm.gpt );
148
149    // get ppn and attributes from slot[0] of kernel GPT
150    hal_gpt_get_pte( k_gpt_xp , 0 , &attr , &ppn );
151
152#if DEBUG_HAL_VMM
153printk("\n[%s] thread[%x,%x] get PT1[0] ( ppn %x / attr %x ) from kernel  GPT\n", 
154__FUNCTION__, this->process->pid, this->trdid, ppn, attr );
155#endif
156
157    // get extended pointer on user GPT
158    xptr_t u_gpt_xp = XPTR( cxy , &process->vmm.gpt );
159
160    // update user GPT : set PTE1 in slot[0]
161    error = hal_gpt_set_pte( u_gpt_xp , 0 , attr , ppn );
162
163    if( error )
164    {
165        printk("\n[ERROR] in %s : cannot update user GPT in cluster %x\n",
166        __FUNCTION__ , cxy );
167        return -1;
168    }
169
170#if DEBUG_HAL_VMM
171printk("\n[%s] thread[%x,%x] registered PT1[0] ( ppn %x / attr %x ) to user GPT\n", 
172__FUNCTION__, this->process->pid, this->trdid, ppn, attr );
173#endif
174
175    // get pointer on the unique vseg registered in kernel VSL
176    xptr_t   root_xp = XPTR( cxy , &process_zero.vmm.vsegs_root );
177    xptr_t   vseg_xp = XLIST_FIRST( root_xp , vseg_t , xlist );
178    vseg_t * vseg    = GET_PTR( vseg_xp );
179
180// check vsegs_nr
181assert( (process_zero.vmm.vsegs_nr == 1 ) ,
182"bad vsegs number in kernel VSL = %d\n", process_zero.vmm.vsegs_nr );
183
184    // update user VSL : register one new vseg for kcode
185    vseg_t * new = vmm_create_vseg( process,
186                                    vseg->type,
187                                    vseg->min,
188                                    vseg->max - vseg->min,
189                                    0, 0,                  // file ofset and file size (unused)
190                                    XPTR_NULL,             // no mapper
191                                    local_cxy );
192    if( new == NULL )
193    {
194        printk("\n[ERROR] in %s : cannot update user VSL in cluster %x\n",
195        __FUNCTION__ , cxy );
196        return -1;
197    }
198
199#if DEBUG_HAL_VMM
200printk("\n[%s] thread[%x,%x] created vseg %s ( base %x / size %x ) to user VSL\n", 
201__FUNCTION__, this->process->pid, this->trdid,
202vseg_type_str(vseg->type) , vseg->min, (vseg->max - vseg->min) );
203hal_vmm_display( process , true );
204#endif
205
206    return 0;
207
208}  // end hal_vmm_kernel_update()
209
210//////////////////////////////////////////
211void hal_vmm_display( process_t * process,
212                      bool_t      mapping )
213{
214    vmm_t * vmm = &process->vmm;
215    gpt_t * gpt = &vmm->gpt;
216
217    // get pointers on TXT0 chdev
218    xptr_t    txt0_xp  = chdev_dir.txt_tx[0];
219    cxy_t     txt0_cxy = GET_CXY( txt0_xp );
220    chdev_t * txt0_ptr = GET_PTR( txt0_xp );
221
222    // get extended pointer on remote TXT0 lock
223    xptr_t  lock_xp = XPTR( txt0_cxy , &txt0_ptr->wait_lock );
224
225    // get locks protecting the VSL and the GPT
226    remote_rwlock_rd_acquire( XPTR( local_cxy , &vmm->vsegs_lock ) );
227    remote_rwlock_rd_acquire( XPTR( local_cxy , &vmm->gpt_lock ) );
228
229    // get TXT0 lock
230    remote_busylock_acquire( lock_xp );
231
232    nolock_printk("\n***** VSL and GPT for process %x in cluster %x\n",
233    process->pid , local_cxy );
234
235    // scan the list of vsegs
236    xptr_t         root_xp = XPTR( local_cxy , &vmm->vsegs_root );
237    xptr_t         iter_xp;
238    xptr_t         vseg_xp;
239    vseg_t       * vseg;
240    XLIST_FOREACH( root_xp , iter_xp )
241    {
242        vseg_xp = XLIST_ELEMENT( iter_xp , vseg_t , xlist );
243        vseg    = GET_PTR( vseg_xp );
244
245        nolock_printk(" - %s : base = %X / size = %X / npages = %d\n",
246        vseg_type_str( vseg->type ) , vseg->min , vseg->max - vseg->min , vseg->vpn_size );
247
248        if( mapping )
249        {
250            vpn_t    vpn     = vseg->vpn_base;
251            vpn_t    vpn_max = vpn + vseg->vpn_size;
252            ppn_t    ppn;
253            uint32_t attr;
254
255            while( vpn < vpn_max )
256            {
257                hal_gpt_get_pte( XPTR( local_cxy , gpt ) , vpn , &attr , &ppn );
258
259                if( attr & GPT_MAPPED )
260                {
261                    if( attr & GPT_SMALL )
262                    {
263                        nolock_printk("    . SMALL : vpn = %X / attr = %X / ppn = %X\n",
264                        vpn , attr , ppn );
265                        vpn++;
266                    }
267                    else
268                    {
269                        nolock_printk("    . BIG   : vpn = %X / attr = %X / ppn = %X\n",
270                        vpn , attr , ppn );
271                        vpn += 512;
272                    }
273                }
274                else
275                {
276                    vpn++;
277                }
278            }
279        }
280    }
281
282    // release TXT0 lock
283    remote_busylock_release( lock_xp );
284
285    // release the VSK and GPT locks
286    remote_rwlock_rd_release( XPTR( local_cxy , &vmm->vsegs_lock ) );
287    remote_rwlock_rd_release( XPTR( local_cxy , &vmm->gpt_lock ) );
288
289}  // hal_vmm_display()
290
Note: See TracBrowser for help on using the repository browser.