source: soft/giet_vm/giet_kernel/kernel_init.c @ 478

Last change on this file since 478 was 478, checked in by alain, 9 years ago

1) The chained buffer structure has been modified to have one single buffer descriptor per cache line (64 bytes),
in order to simplify the software cache coherence between L2 and L3 caches when the IO bridge is used.
A new buffer_descriptor_t structure has been defined, and the fbf_chbuf_t and nic_chbuf_t structures have been adapted.
2) The NIC related system call handler _sys_nic_start() and _sys_nic_move() have been modified to support a distributed
kernel chbuf (one 4 Kbytes buffer per cluster), in order to support the one Gbit Ethernet NIC controller throughput.

  • the _sys_nic_start() function initialises the distributed chbuf, using the distributed heap.
  • the _sys_nic_move() function transfer one 4 KBytes container from the local kernel chbuf to an user local buffer.

This approach has been validated on the "classif" application: no packet loss with 16 clusters for average packet
length = 600 bytes and inter-packet gap = 300 cycles.

  • Property svn:executable set to *
File size: 14.1 KB
Line 
1///////////////////////////////////////////////////////////////////////////////////
2// File     : kernel_init.c
3// Date     : 26/05/2012
4// Authors  : alain greiner & mohamed karaoui
5// Copyright (c) UPMC-LIP6
6////////////////////////////////////////////////////////////////////////////////////
7// This kernel_init.c file is part of the GIET-VM nano-kernel.
8////////////////////////////////////////////////////////////////////////////////////
9
10#include <giet_config.h>
11#include <hard_config.h>
12#include <utils.h>
13#include <tty0.h>
14#include <kernel_malloc.h>
15#include <fat32.h>
16#include <xcu_driver.h>
17#include <ioc_driver.h>
18#include <mmc_driver.h>
19#include <ctx_handler.h>
20#include <irq_handler.h>
21#include <mapping_info.h>
22#include <mips32_registers.h>
23
24#if !defined(X_SIZE)
25# error: You must define X_SIZE in the hard_config.h file
26#endif
27
28#if !defined(Y_SIZE)
29# error: You must define Y_SIZE in the hard_config.h file
30#endif
31
32#if !defined(Y_WIDTH)
33# error: You must define Y_WIDTH in the hard_config.h file
34#endif
35
36#if !defined(Y_WIDTH)
37# error: You must define Y_WIDTH in the hard_config.h file
38#endif
39
40#if !defined(NB_PROCS_MAX)
41# error: You must define NB_PROCS_MAX in the hard_config.h file
42#endif
43
44#if !defined(NB_TOTAL_PROCS)
45# error: You must define NB_TOTAL_PROCS in the hard_config.h file
46#endif
47
48#if !defined(USE_XCU)
49# error: You must define USE_XCU in the hard_config.h file
50#endif
51
52#if !defined(IDLE_TASK_INDEX)
53# error: You must define IDLE_TASK_INDEX in the ctx_handler.h file
54#endif
55
56#if !defined(GIET_TICK_VALUE)
57# error: You must define GIET_TICK_VALUE in the giet_config.h file
58#endif
59
60#if !defined(GIET_NB_VSPACE_MAX)
61# error: You must define GIET_NB_VSPACE_MAX in the giet_config.h file
62#endif
63
64#if !defined(NB_TTY_CHANNELS)
65# error: You must define NB_TTY_CHANNELS in the hard_config.h file
66#endif
67
68#if (NB_TTY_CHANNELS < 1)
69# error: NB_TTY_CHANNELS cannot be smaller than 1
70#endif
71
72
73
74///////////////////////////////////////////////////////////////////////////////////
75// Ditributed kernel heap descriptors array (for dynamic memory allocation)
76///////////////////////////////////////////////////////////////////////////////////
77
78kernel_heap_t  kernel_heap[X_SIZE][Y_SIZE];
79
80///////////////////////////////////////////////////////////////////////////////////
81// FAT internal representation for kernel code
82///////////////////////////////////////////////////////////////////////////////////
83
84fat32_fs_t     fat      __attribute__((aligned(512)));
85
86///////////////////////////////////////////////////////////////////////////////////
87// array of pointers on the page tables (virtual addresses)
88///////////////////////////////////////////////////////////////////////////////////
89
90volatile unsigned int _ptabs_vaddr[GIET_NB_VSPACE_MAX];    // virtual addresses
91volatile unsigned int _ptabs_ptprs[GIET_NB_VSPACE_MAX];    // physical addresses >> 13
92
93///////////////////////////////////////////////////////////////////////////////////
94// Array of pointers on the schedulers (physical addresses)
95///////////////////////////////////////////////////////////////////////////////////
96
97volatile static_scheduler_t*    _schedulers[X_SIZE][Y_SIZE][NB_PROCS_MAX]; 
98
99////////////////////////////////////////////////////////////////////////////////////
100// Synchonisation barrier before jumping to user code
101////////////////////////////////////////////////////////////////////////////////////
102
103volatile unsigned int kernel_init_barrier = 0;
104
105////////////////////////////////////////////////////////////////////////////////////
106// Global variables for TTY/kernel communications
107////////////////////////////////////////////////////////////////////////////////////
108
109unsigned int   _tty_rx_buf[NB_TTY_CHANNELS];
110unsigned int   _tty_rx_full[NB_TTY_CHANNELS]; 
111
112////////////////////////////////////////////////////////////////////////////////////
113// Distributed locks protecting TTY terminals       
114////////////////////////////////////////////////////////////////////////////////////
115
116sbt_lock_t     _tty_tx_lock[NB_TTY_CHANNELS]  __attribute__((aligned(64)));
117
118///////////////////////////////////////////////////////////////////////////////////
119// This kernel_init() function completes the kernel initialisation in 7 steps:
120// All processors execute this code, but this is done sequencially.
121// - step 0 : Initialise fat, heap descriptors, and tty locks
122// - step 1 : Initialise scheduler pointers array
123// - step 2 : Initialise PTAB pointers arrays
124// - step 3 : Initialise private XCU masks
125// - step 4 :
126// - step 5 :
127// - step 6 :
128///////////////////////////////////////////////////////////////////////////////////
129__attribute__((section (".kinit"))) void kernel_init() 
130{
131    // gpid : hardware processor index (fixed format: X_WIDTH|Y_WIDTH|P_WIDTH)
132    // p    : local processor id in a cluster ( p < NB_PROCS_MAX)
133    // cpid : continuous processor index = (((x * Y_SIZE + y) * NB_PROCS_MAX) + p
134
135    unsigned int gpid       = _get_procid();
136    unsigned int cluster_xy = gpid >> P_WIDTH;
137    unsigned int x          = cluster_xy >> Y_WIDTH & ((1<<X_WIDTH)-1);
138    unsigned int y          = cluster_xy & ((1<<Y_WIDTH)-1);
139    unsigned int p          = gpid & ((1<<P_WIDTH)-1);
140    unsigned int cpid       = ((( x * Y_SIZE) + y) * NB_PROCS_MAX) + p;
141
142    // This initialisation is done sequencially by each processor
143    while( cpid != kernel_init_barrier ) asm volatile ( "nop" );
144
145    // Step 0 : P[0,0,0] initialises various complex structures
146    //          - kernel FAT
147    //          - distributed kernel heaps
148    //          - distributed locks protecting TTY channels
149    //          - distributed locks protecting MMC components
150    if ( gpid == 0 )
151    {
152        _heap_init();
153       
154#if GIET_DEBUG_INIT
155_nolock_printf("\n[DEBUG KERNEL_INIT] P[%d,%d,%d] completes kernel HEAP init\n", x, y, p );
156#endif
157        unsigned int channel;
158        for ( channel = 0 ; channel < NB_TTY_CHANNELS ; channel++ )
159        {
160            _sbt_lock_init( &_tty_tx_lock[channel] );
161
162#if GIET_DEBUG_INIT
163_nolock_printf("\n[DEBUG KERNEL_INIT] P[%d,%d,%d] completes TTY[%d] lock init\n", 
164               x , y , p , channel );
165#endif
166        }
167
168/*
169        unsigned int cx, cy;
170        for ( cx = 0 ; cx < X_SIZE ; cx++ )
171        {
172            for ( cy = 0 ; cy < X_SIZE ; cy++ )
173            {
174                _sbt_lock_init( &_mmc_lock[cx][cy] );
175
176#if GIET_DEBUG_INIT
177_nolock_printf("\n[DEBUG KERNEL_INIT] P[%d,%d,%d] completes MMC[%d][%d] lock init\n",
178               x , y , p , cx , cy );
179#endif
180            }
181        }
182*/
183        _fat_init( IOC_BOOT_MODE ); 
184
185#if GIET_DEBUG_INIT
186_nolock_printf("\n[DEBUG KERNEL_INIT] P[%d,%d,%d] completes kernel FAT init\n", x, y, p );
187#endif
188
189    }
190
191    // Step 1 : each processor get its scheduler virtual address from CP0_SCHED register
192    //          and contributes to _schedulers[] array initialisation
193
194    static_scheduler_t* psched     = (static_scheduler_t*)_get_sched();
195    unsigned int        tasks      = psched->tasks;
196
197    _schedulers[x][y][p] = psched;
198
199#if GIET_DEBUG_INIT
200_nolock_printf("\n[DEBUG KERNEL_INIT] P[%d,%d,%d] initialises SCHED array\n"
201               " - scheduler vbase = %x\n"
202               " - tasks           = %d\n",
203               x, y, p, (unsigned int)psched, tasks );
204#endif
205
206    // step 2 : each processor that is allocated at least one task loops
207    //          on all allocated tasks:
208    //          - contributes to _ptabs_vaddr[] & _ptabs_ptprs[] initialisation.
209    //          - set CTX_RA slot  with the kernel _ctx_eret() virtual address.
210    //          - set CTX_EPC slot that must contain the task entry point,
211    //            and contain only at this point the virtual address of the memory
212    //            location containing this entry point.
213
214    unsigned int ltid;
215
216    for (ltid = 0; ltid < tasks; ltid++) 
217    {
218        unsigned int vsid = _get_task_slot( x, y, p, ltid , CTX_VSID_ID ); 
219        unsigned int ptab = _get_task_slot( x, y, p, ltid , CTX_PTAB_ID ); 
220        unsigned int ptpr = _get_task_slot( x, y, p, ltid , CTX_PTPR_ID ); 
221
222        // initialize PTABS arrays
223        _ptabs_vaddr[vsid] = ptab;
224        _ptabs_ptprs[vsid] = ptpr;
225
226#if GIET_DEBUG_INIT
227_nolock_printf("\n[DEBUG KERNEL_INIT] P[%d,%d,%d] initialises PTABS arrays\n"
228        " - ptabs_vaddr[%d] = %x / ptpr_paddr[%d] = %l\n",
229        x, y, p, 
230        vsid, ptab, vsid, ((unsigned long long)ptpr)<<13 );
231#endif
232
233        // set the ptpr to use the task page table
234        asm volatile( "mtc2    %0,   $0   \n"
235                      : : "r" (ptpr) );
236
237        // compute ctx_ra
238        unsigned int ctx_ra = (unsigned int)(&_ctx_eret);
239        _set_task_slot( x, y, p, ltid, CTX_RA_ID, ctx_ra );
240
241        // compute ctx_epc
242        unsigned int* ptr = (unsigned int*)_get_task_slot( x, y, p, ltid, CTX_EPC_ID );
243        _set_task_slot( x, y, p, ltid, CTX_EPC_ID, *ptr );
244
245#if GIET_DEBUG_INIT
246_nolock_printf("\n[DEBUG KERNEL_INIT] P[%d,%d,%d] updates context for task %d\n"
247               " - ctx_epc   = %x\n"
248               " - ctx_ra    = %x\n",
249               x, y, p, ltid,
250               _get_task_slot( x, y, p, ltid, CTX_EPC_ID ),
251               _get_task_slot( x, y, p, ltid, CTX_RA_ID ) );
252#endif
253
254    }  // end for tasks
255
256    // step 3 : compute and set XCU masks
257
258    unsigned int isr_switch_index = 0xFFFFFFFF;
259    unsigned int hwi_mask = 0;
260    unsigned int pti_mask = 0;
261    unsigned int wti_mask = 0;
262    unsigned int irq_id;            // IN_IRQ index
263    unsigned int entry;             // interrupt vector entry
264
265    for (irq_id = 0; irq_id < 32; irq_id++) 
266    {
267        entry = psched->hwi_vector[irq_id];
268        if ( entry & 0x80000000 ) hwi_mask = hwi_mask | (1<<irq_id);
269        if ( (entry & 0x0000FFFF) == ISR_TICK ) isr_switch_index = irq_id;
270
271        entry = psched->pti_vector[irq_id];
272        if ( entry & 0x80000000 ) pti_mask = pti_mask | (1<<irq_id);
273        if ( (entry & 0x0000FFFF) == ISR_TICK ) isr_switch_index = irq_id;
274
275        entry = psched->wti_vector[irq_id];
276        if ( entry & 0x80000000 ) wti_mask = wti_mask | (1<<irq_id);
277        if ( (entry & 0x0000FFFF) == ISR_TICK ) isr_switch_index = irq_id;
278    }
279
280#if GIET_DEBUG_INIT
281_nolock_printf("\n[DEBUG KERNEL_INIT] P[%d,%d,%d] sets XCU masks\n"
282               " - XCU HWI_MASK = %x\n"
283               " - XCU WTI_MASK = %x\n"
284               " - XCU PTI_MASK = %x\n",
285               x, y, p, hwi_mask, wti_mask, pti_mask );
286#endif
287
288    unsigned int channel = p * IRQ_PER_PROCESSOR; 
289
290    _xcu_set_mask( cluster_xy, channel, hwi_mask, IRQ_TYPE_HWI ); 
291    _xcu_set_mask( cluster_xy, channel, wti_mask, IRQ_TYPE_WTI );
292    _xcu_set_mask( cluster_xy, channel, pti_mask, IRQ_TYPE_PTI );
293
294    // step 4 : start TICK timer if at least one task
295    if (tasks > 0) 
296    {
297        // one ISR_TICK must be defined for each proc
298        if (isr_switch_index == 0xFFFFFFFF) 
299        {
300            _nolock_printf("\n[GIET ERROR] ISR_TICK not found for processor[%d,%d,%d]\n",
301                           x, y, p );
302            _exit();
303        }
304
305        // start system timer
306        _xcu_timer_start( cluster_xy, isr_switch_index, GIET_TICK_VALUE ); 
307
308    }
309
310#if GIET_DEBUG_INIT
311_nolock_printf("\n[DEBUG KERNEL_INIT] P[%d,%d,%d] starts TICK timer\n",
312               x, y, p );
313#endif
314
315    // step 5 : each processor updates the idle_task context:
316    //          (CTX_SP, CTX_RA, CTX_EPC).
317    //          The 4 Kbytes idle stack is implemented in the scheduler.
318    //          The PTPR register, the CTX_PTPR and CTX_PTAB slots
319    //          have been initialised in boot code.
320
321    unsigned int pstack = ((unsigned int)psched) + 0x2000;
322
323    _set_task_slot( x, y, p, IDLE_TASK_INDEX, CTX_SP_ID,  pstack);
324    _set_task_slot( x, y, p, IDLE_TASK_INDEX, CTX_RA_ID,  (unsigned int) &_ctx_eret);
325    _set_task_slot( x, y, p, IDLE_TASK_INDEX, CTX_EPC_ID, (unsigned int) &_idle_task);
326
327#if GIET_DEBUG_INIT
328_nolock_printf("\n[DEBUG KERNEL_INIT] P[%d,%d,%d] initializes IDLE task\n"
329               " - stack_base = %x\n"
330               " - stack_size = 0x1000\n",
331               x, y, p, pstack - 0x1000 );
332#endif
333
334    // step 6 : when all processors reach the synchronisation barrier,
335    //          each processor set registers SP, SR, PTPR, EPC,
336    //          with the values corresponding to the first allocated task,
337    //          or to the idle_task if there is no task allocated,
338    //          and jump to user code
339
340    if (tasks == 0) 
341    {
342        ltid = IDLE_TASK_INDEX;
343
344        _nolock_printf("\n[GIET WARNING] No task allocated to processor[%d,%d,%d]\n",
345                       x, y, p );
346    }
347    else
348    {
349        ltid = 0;
350    }
351
352    unsigned int sp_value   = _get_task_slot( x, y, p, ltid, CTX_SP_ID);
353    unsigned int sr_value   = _get_task_slot( x, y, p, ltid, CTX_SR_ID);
354    unsigned int ptpr_value = _get_task_slot( x, y, p, ltid, CTX_PTPR_ID);
355    unsigned int epc_value  = _get_task_slot( x, y, p, ltid, CTX_EPC_ID);
356
357#if GIET_DEBUG_INIT
358_nolock_printf("\n[DEBUG KERNEL_INIT] P[%d,%d,%d] reach barrier at cycle %d\n",
359               x, y, p, _get_proctime() );
360#endif
361
362    // increment barrier counter
363    kernel_init_barrier++;
364
365    // busy waiting until all processors synchronized
366    while ( kernel_init_barrier != NB_TOTAL_PROCS );
367
368#if GIET_DEBUG_INIT
369_printf("\n[DEBUG KERNEL_INIT] P[%d,%d,%d] initializes registers at cycle %d\n"
370        " - sp   = %x\n"
371        " - sr   = %x\n"
372        " - ptpr = %x\n"
373        " - epc  = %x\n",
374        x, y, p, _get_proctime(),
375        sp_value, sr_value, ptpr_value, epc_value );
376#endif
377
378    // set registers and jump to user code
379    asm volatile ( "move  $29,  %0                  \n"   /* SP <= ctx[CTX_SP_ID] */
380                   "mtc0  %1,   $12                 \n"   /* SR <= ctx[CTX_SR_ID] */
381                   "mtc2  %2,   $0                  \n"   /* PTPR <= ctx[CTX_PTPR] */
382                   "mtc0  %3,   $14                 \n"   /* EPC <= ctx[CTX_EPC]  */
383                   "eret                            \n"   /* jump to user code  */
384                   "nop                             \n"
385                   : 
386                   : "r"(sp_value), "r"(sr_value), "r"(ptpr_value), "r"(epc_value)
387                   : "$29", "memory" );
388
389} // end kernel_init()
390
391
392// Local Variables:
393// tab-width: 4
394// c-basic-offset: 4
395// c-file-offsets:((innamespace . 0)(inline-open . 0))
396// indent-tabs-mode: nil
397// End:
398// vim: filetype=c:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
399
Note: See TracBrowser for help on using the repository browser.