source: soft/giet_vm/boot/boot_init.c @ 256

Last change on this file since 256 was 255, checked in by meunier, 11 years ago
  • Added a syscall and some user functions to manipulate the Simulation Helper
  • Changed the the way the Vseg -> Pseg mapping is made during the boot to better utilize the address space (+ adaptation of the algorithm in memo)
  • Fixed a bug in boot_init (vobj_init): the vobj initialization could only be made for the first application (ptpr was not changed)
File size: 75.9 KB
RevLine 
[189]1//////////////////////////////////////////////////////////////////////////////////
2// File     : boot_init.c
3// Date     : 01/04/2012
4// Author   : alain greiner
5// Copyright (c) UPMC-LIP6
6///////////////////////////////////////////////////////////////////////////////////
7// The boot_init.c file is part of the GIET-VM nano-kernel.
8// This code is executed in the boot phase by proc[0] to initialize the
[238]9// peripherals and the kernel data structures:
[189]10// - pages tables for the various vspaces
11// - shedulers for processors (including the tasks contexts and interrupt vectors)
12//
[238]13// This nano-kernel has been written for the MIPS32 processor.
14// The virtual adresses are on 32 bits and use the (unsigned int) type, but the
15// physicals addresses can have up to 40 bits, and use the  (unsigned long long) type.
16//
[189]17// The GIET-VM uses the paged virtual memory and the MAPPING_INFO binary file
18// to provides two services:
19// 1) classical memory protection, when several independant applications compiled
20//    in different virtual spaces are executing on the same hardware platform.
21// 2) data placement in NUMA architectures, when we want to control the placement
22//    of the software objects (virtual segments) on the physical memory banks.
23//
24// The MAPPING_INFO binary data structure must be loaded in the the seg_boot_mapping
25// segment (at address seg_mapping_base).
[238]26// This MAPPING_INFO data structure defines
27// - the hardware architecture: number of clusters, number or processors,
28//   size of the memory segments, and peripherals in each cluster.
29// - The structure of the various multi-threaded software applications:
30//   number of tasks, communication channels.
31// - The mapping: placement of virtual objects (vobj) in the virtual segments (vseg),
32//   placement of virtual segments (vseg) in the physical segments (pseg), placement
33//   of software tasks on the processors,
[189]34//
[199]35// The page table are statically build in the boot phase, and they do not
[189]36// change during execution. The GIET uses only 4 Kbytes pages.
37// As most applications use only a limited number of segments, the number of PT2s
38// actually used by a given virtual space is generally smaller than 2048, and is
[199]39// computed during the boot phase.
[189]40// The max number of virtual spaces (GIET_NB_VSPACE_MAX) is a configuration parameter.
41//
[238]42// Each page table (one page table per virtual space) is monolithic, and contains
43// one PT1 and up to (GIET_NB_PT2_MAX) PT2s. The PT1 is addressed using the ix1 field
[189]44// (11 bits) of the VPN, and the selected PT2 is addressed using the ix2 field (9 bits).
[238]45// - PT1[2048] : a first 8K aligned array of unsigned int, indexed by (ix1) field of VPN.
[189]46//   Each entry in the PT1 contains a 32 bits PTD. The MSB bit PTD[31] is
47//   the PTD valid bit, and LSB bits PTD[19:0] are the 20 MSB bits of the physical base
48//   address of the selected PT2.
49//   The PT1 contains 2048 PTD of 4 bytes => 8K bytes.
50// - PT2[1024][GIET_NB_PT2_MAX] : an array of array of unsigned int.
[238]51//   Each PT2[1024] must be 4K aligned, each entry in a PT2 contains two unsigned int:
[189]52//   the first word contains the protection flags, and the second word contains the PPN.
53//   Each PT2 contains 512 PTE2 of 8bytes => 4K bytes.
54// The total size of a page table is finally = 8K + (GIET_NB_PT2_MAX)*4K bytes.
55////////////////////////////////////////////////////////////////////////////////////
56
57#include <common.h>
58#include <mips32_registers.h>
59#include <giet_config.h>
60#include <mapping_info.h>
61#include <mwmr_channel.h>
62#include <barrier.h>
[228]63#include <memspace.h>
[189]64#include <irq_handler.h>
65#include <ctx_handler.h>
66#include <vm_handler.h>
67#include <hwr_mapping.h>
68
69#include <stdarg.h>
70
[255]71
[228]72#if !defined(NB_CLUSTERS)
[189]73# error The NB_CLUSTERS value must be defined in the 'giet_config.h' file !
74#endif
75
[228]76#if !defined(NB_PROCS_MAX)
[189]77# error The NB_PROCS_MAX value must be defined in the 'giet_config.h' file !
78#endif
79
[228]80#if !defined(GIET_NB_VSPACE_MAX)
[189]81# error The GIET_NB_VSPACE_MAX value must be defined in the 'giet_config.h' file !
82#endif
83
[255]84#define max(x, y) (((x) > (y)) ? (x) : (y))
85
86
[189]87////////////////////////////////////////////////////////////////////////////
88//      Global variables for boot code
[238]89// Both the page tables for the various virtual spaces, and the schedulers
90// for the processors are physically distributed on the clusters.
91// These global variables are just arrays of pointers.
[189]92////////////////////////////////////////////////////////////////////////////
93
[238]94// Page table addresses arrays
[245]95__attribute__((section (".wdata"))) 
[238]96paddr_t      boot_ptabs_paddr[GIET_NB_VSPACE_MAX];
[245]97
98__attribute__((section (".wdata"))) 
[238]99unsigned int boot_ptabs_vaddr[GIET_NB_VSPACE_MAX];
[189]100
[238]101// Scheduler pointers array (virtual addresses)
[245]102__attribute__((section (".wdata"))) 
[238]103static_scheduler_t* boot_schedulers[NB_CLUSTERS * NB_PROCS_MAX];
[189]104
105// Next free PT2 index array
[245]106__attribute__((section (".wdata"))) 
[228]107unsigned int boot_next_free_pt2[GIET_NB_VSPACE_MAX] =
108{ [0 ... GIET_NB_VSPACE_MAX - 1] = 0 };
[189]109
110// Max PT2 index
[245]111__attribute__((section (".wdata"))) 
[228]112unsigned int boot_max_pt2[GIET_NB_VSPACE_MAX] =
113{ [0 ... GIET_NB_VSPACE_MAX - 1] = 0 };
[189]114
[249]115// lock protecting TTY0
116__attribute__((section (".wdata"))) 
117unsigned int boot_tty0_lock = 0;
[189]118
[249]119
[189]120//////////////////////////////////////////////////////////////////////////////
121// boot_procid()
122//////////////////////////////////////////////////////////////////////////////
[238]123inline unsigned int boot_procid() 
124{
[189]125    unsigned int ret;
[228]126    asm volatile ("mfc0 %0, $15, 1":"=r" (ret));
[189]127    return (ret & 0x3FF);
128}
[228]129
[189]130//////////////////////////////////////////////////////////////////////////////
131// boot_proctime()
132//////////////////////////////////////////////////////////////////////////////
[238]133inline unsigned int boot_proctime() 
134{
[189]135    unsigned int ret;
[228]136    asm volatile ("mfc0 %0, $9":"=r" (ret));
[189]137    return ret;
138}
[228]139
[189]140//////////////////////////////////////////////////////////////////////////////
141// boot_exit()
142//////////////////////////////////////////////////////////////////////////////
[238]143void boot_exit() 
144{
145    while (1) { asm volatile ("nop"); }
[189]146}
[228]147
[189]148//////////////////////////////////////////////////////////////////////////////
149// boot_eret()
150// The address of this function is used to initialise the return address (RA)
151// in all task contexts (when the task has never been executed.
152/////////////////////////////////"/////////////////////////////////////////////
[238]153void boot_eret() 
154{
[228]155    asm volatile ("eret");
[189]156}
[228]157
[238]158////////////////////////////////////////////////////////////////////////////
159// boot_physical_read()
160// This function makes a physical read access to a 32 bits word in memory,
161// after a temporary DTLB de-activation and paddr extension.
162////////////////////////////////////////////////////////////////////////////
163unsigned int boot_physical_read(paddr_t paddr) 
164{
[215]165    unsigned int value;
[246]166    unsigned int lsb = (unsigned int) paddr;
167    unsigned int msb = (unsigned int) (paddr >> 32);
[215]168
[238]169    asm volatile(
170            "mfc2   $2,     $1                 \n"     /* $2 <= MMU_MODE   */
171            "andi   $3,     $2,        0xb     \n"
172            "mtc2   $3,     $1                 \n"     /* DTLB off         */   
[228]173
[238]174            "mtc2   %2,     $24                \n"     /* PADDR_EXT <= msb */   
175            "lw     %0,     0(%1)              \n"     /* value <= *paddr  */
176            "mtc2   $0,     $24                \n"     /* PADDR_EXT <= 0   */   
[215]177
[238]178            "mtc2   $2,     $1                 \n"     /* restore MMU_MODE */
179            : "=r" (value)
180            : "r" (lsb), "r" (msb)
181            : "$2", "$3");
[215]182    return value;
183}
184
[238]185////////////////////////////////////////////////////////////////////////////
186// boot_physical_write()
187// This function makes a physical write access to a 32 bits word in memory,
188// after a temporary DTLB de-activation and paddr extension.
189////////////////////////////////////////////////////////////////////////////
190void boot_physical_write(paddr_t      paddr, 
191                         unsigned int value) 
192{
193    unsigned int lsb = (unsigned int)paddr;
194    unsigned int msb = (unsigned int)(paddr >> 32);
[228]195
[238]196    asm volatile(
197            "mfc2   $2,     $1                 \n"     /* $2 <= MMU_MODE   */
198            "andi   $3,     $2,        0xb     \n"
199            "mtc2   $3,     $1                 \n"     /* DTLB off         */   
[189]200
[238]201            "mtc2   %2,     $24                \n"     /* PADDR_EXT <= msb */   
202            "sw     %0,     0(%1)              \n"     /* *paddr <= value  */
203            "mtc2   $0,     $24                \n"     /* PADDR_EXT <= 0   */   
[228]204
[238]205            "mtc2   $2,     $1                 \n"     /* restore MMU_MODE */
[228]206            :
[238]207            : "r" (value), "r" (lsb), "r" (msb)
208            : "$2", "$3");
[189]209}
[228]210
[189]211//////////////////////////////////////////////////////////////////////////////
212// boot_set_mmu_ptpr()
213// This function set a new value for the MMU PTPR register.
214//////////////////////////////////////////////////////////////////////////////
[238]215inline void boot_set_mmu_ptpr(unsigned int val) 
216{
[228]217    asm volatile ("mtc2  %0, $0"::"r" (val));
[189]218}
219
220//////////////////////////////////////////////////////////////////////////////
221// boot_set_mmu_mode()
222// This function set a new value for the MMU MODE register.
223//////////////////////////////////////////////////////////////////////////////
[238]224inline void boot_set_mmu_mode(unsigned int val) 
225{
[228]226    asm volatile ("mtc2  %0, $1"::"r" (val));
[189]227}
[228]228
[189]229////////////////////////////////////////////////////////////////////////////
230// boot_puts()
[238]231// display a string on TTY0
[189]232////////////////////////////////////////////////////////////////////////////
[238]233void boot_puts(const char * buffer) 
234{
[228]235    unsigned int *tty_address = (unsigned int *) &seg_tty_base;
[189]236    unsigned int n;
237
[238]238    for (n = 0; n < 100; n++) 
239    {
240        if (buffer[n] == 0)  break; 
[228]241        tty_address[TTY_WRITE] = (unsigned int) buffer[n];
[189]242    }
[228]243}
244
[189]245////////////////////////////////////////////////////////////////////////////
[204]246// boot_putx()
[238]247// display a 32 bits unsigned int as an hexadecimal string on TTY0
[189]248////////////////////////////////////////////////////////////////////////////
[238]249void boot_putx(unsigned int val) 
250{
[228]251    static const char HexaTab[] = "0123456789ABCDEF";
252    char buf[11];
253    unsigned int c;
[189]254
[228]255    buf[0] = '0';
256    buf[1] = 'x';
[189]257    buf[10] = 0;
258
[238]259    for (c = 0; c < 8; c++) 
260    {
[228]261        buf[9 - c] = HexaTab[val & 0xF];
[189]262        val = val >> 4;
263    }
264    boot_puts(buf);
265}
[228]266
[238]267////////////////////////////////////////////////////////////////////////////
268// boot_putl()
269// display a 64 bits unsigned long as an hexadecimal string on TTY0
270////////////////////////////////////////////////////////////////////////////
271void boot_putl(paddr_t val) 
272{
273    static const char HexaTab[] = "0123456789ABCDEF";
274    char buf[19];
275    unsigned int c;
[228]276
[238]277    buf[0] = '0';
278    buf[1] = 'x';
279    buf[18] = 0;
280
281    for (c = 0; c < 16; c++) 
282    {
283        buf[17 - c] = HexaTab[(unsigned int)val & 0xF];
284        val = val >> 4;
285    }
286    boot_puts(buf);
287}
288
[204]289////////////////////////////////////////////////////////////////////////////
290// boot_putd()
[238]291// display a 32 bits unsigned int as a decimal string on TTY0
[204]292////////////////////////////////////////////////////////////////////////////
[238]293void boot_putd(unsigned int val) 
294{
[228]295    static const char DecTab[] = "0123456789";
296    char buf[11];
297    unsigned int i;
298    unsigned int first;
[189]299
[204]300    buf[10] = 0;
301
[238]302    for (i = 0; i < 10; i++) 
303    {
304        if ((val != 0) || (i == 0)) 
305        {
[228]306            buf[9 - i] = DecTab[val % 10];
307            first = 9 - i;
[204]308        }
[238]309        else 
310        {
[204]311            break;
312        }
313        val /= 10;
314    }
[228]315    boot_puts(&buf[first]);
[204]316}
317
[189]318/////////////////////////////////////////////////////////////////////////////
319//  mapping_info data structure access functions
320/////////////////////////////////////////////////////////////////////////////
[238]321inline mapping_cluster_t *boot_get_cluster_base(mapping_header_t * header) 
322{
[228]323    return (mapping_cluster_t *) ((char *) header + MAPPING_HEADER_SIZE);
[189]324}
325/////////////////////////////////////////////////////////////////////////////
[238]326inline mapping_pseg_t *boot_get_pseg_base(mapping_header_t * header) 
327{
[228]328    return (mapping_pseg_t *) ((char *) header +
329            MAPPING_HEADER_SIZE +
330            MAPPING_CLUSTER_SIZE * header->clusters);
[189]331}
332/////////////////////////////////////////////////////////////////////////////
[238]333inline mapping_vspace_t *boot_get_vspace_base(mapping_header_t * header) 
334{
[228]335    return (mapping_vspace_t *) ((char *) header +
336            MAPPING_HEADER_SIZE +
337            MAPPING_CLUSTER_SIZE * header->clusters +
338            MAPPING_PSEG_SIZE * header->psegs);
[189]339}
340/////////////////////////////////////////////////////////////////////////////
[238]341inline mapping_vseg_t *boot_get_vseg_base(mapping_header_t * header) 
342{
[228]343    return (mapping_vseg_t *) ((char *) header +
344            MAPPING_HEADER_SIZE +
345            MAPPING_CLUSTER_SIZE * header->clusters +
346            MAPPING_PSEG_SIZE * header->psegs +
347            MAPPING_VSPACE_SIZE * header->vspaces);
[189]348}
349/////////////////////////////////////////////////////////////////////////////
[238]350inline mapping_vobj_t *boot_get_vobj_base(mapping_header_t * header) 
351{
[228]352    return (mapping_vobj_t *) ((char *) header +
353            MAPPING_HEADER_SIZE +
354            MAPPING_CLUSTER_SIZE * header->clusters +
355            MAPPING_PSEG_SIZE * header->psegs +
356            MAPPING_VSPACE_SIZE * header->vspaces +
357            MAPPING_VSEG_SIZE * header->vsegs);
[189]358}
359/////////////////////////////////////////////////////////////////////////////
[238]360inline mapping_task_t *boot_get_task_base(mapping_header_t * header) 
361{
[228]362    return (mapping_task_t *) ((char *) header +
363            MAPPING_HEADER_SIZE +
364            MAPPING_CLUSTER_SIZE * header->clusters +
365            MAPPING_PSEG_SIZE * header->psegs +
366            MAPPING_VSPACE_SIZE * header->vspaces +
367            MAPPING_VSEG_SIZE * header->vsegs +
368            MAPPING_VOBJ_SIZE * header->vobjs);
[189]369}
370/////////////////////////////////////////////////////////////////////////////
[238]371inline mapping_proc_t *boot_get_proc_base(mapping_header_t * header) 
372{
[228]373    return (mapping_proc_t *) ((char *) header +
374            MAPPING_HEADER_SIZE +
375            MAPPING_CLUSTER_SIZE * header->clusters +
376            MAPPING_PSEG_SIZE * header->psegs +
377            MAPPING_VSPACE_SIZE * header->vspaces +
378            MAPPING_VSEG_SIZE * header->vsegs +
379            MAPPING_VOBJ_SIZE * header->vobjs +
380            MAPPING_TASK_SIZE * header->tasks);
[189]381}
382/////////////////////////////////////////////////////////////////////////////
[238]383inline mapping_irq_t *boot_get_irq_base(mapping_header_t * header) 
384{
[228]385    return (mapping_irq_t *) ((char *) header +
386            MAPPING_HEADER_SIZE +
387            MAPPING_CLUSTER_SIZE * header->clusters +
388            MAPPING_PSEG_SIZE * header->psegs +
389            MAPPING_VSPACE_SIZE * header->vspaces +
390            MAPPING_VSEG_SIZE * header->vsegs +
391            MAPPING_VOBJ_SIZE * header->vobjs +
392            MAPPING_TASK_SIZE * header->tasks +
393            MAPPING_PROC_SIZE * header->procs);
[189]394}
395/////////////////////////////////////////////////////////////////////////////
[238]396inline mapping_coproc_t *boot_get_coproc_base(mapping_header_t * header) 
397{
[228]398    return (mapping_coproc_t *) ((char *) header +
399            MAPPING_HEADER_SIZE +
400            MAPPING_CLUSTER_SIZE * header->clusters +
401            MAPPING_PSEG_SIZE * header->psegs +
402            MAPPING_VSPACE_SIZE * header->vspaces +
403            MAPPING_VOBJ_SIZE * header->vobjs +
404            MAPPING_VSEG_SIZE * header->vsegs +
405            MAPPING_TASK_SIZE * header->tasks +
406            MAPPING_PROC_SIZE * header->procs +
407            MAPPING_IRQ_SIZE * header->irqs);
[189]408}
409///////////////////////////////////////////////////////////////////////////////////
[238]410inline mapping_cp_port_t *boot_get_cp_port_base(mapping_header_t * header) 
411{
[228]412    return (mapping_cp_port_t *) ((char *) header +
413            MAPPING_HEADER_SIZE +
414            MAPPING_CLUSTER_SIZE * header->clusters +
415            MAPPING_PSEG_SIZE * header->psegs +
416            MAPPING_VSPACE_SIZE * header->vspaces +
417            MAPPING_VOBJ_SIZE * header->vobjs +
418            MAPPING_VSEG_SIZE * header->vsegs +
419            MAPPING_TASK_SIZE * header->tasks +
420            MAPPING_PROC_SIZE * header->procs +
421            MAPPING_IRQ_SIZE * header->irqs +
422            MAPPING_COPROC_SIZE * header->coprocs);
[189]423}
424///////////////////////////////////////////////////////////////////////////////////
[238]425inline mapping_periph_t *boot_get_periph_base(mapping_header_t * header) 
426{
[228]427    return (mapping_periph_t *) ((char *) header +
428            MAPPING_HEADER_SIZE +
429            MAPPING_CLUSTER_SIZE * header->clusters +
430            MAPPING_PSEG_SIZE * header->psegs +
431            MAPPING_VSPACE_SIZE * header->vspaces +
432            MAPPING_VOBJ_SIZE * header->vobjs +
433            MAPPING_VSEG_SIZE * header->vsegs +
434            MAPPING_TASK_SIZE * header->tasks +
435            MAPPING_PROC_SIZE * header->procs +
436            MAPPING_IRQ_SIZE * header->irqs +
437            MAPPING_COPROC_SIZE * header->coprocs +
438            MAPPING_CP_PORT_SIZE * header->cp_ports);
[189]439}
440
441//////////////////////////////////////////////////////////////////////////////
442//     boot_pseg_get()
443// This function returns the pointer on a physical segment
444// identified  by the pseg index.
445//////////////////////////////////////////////////////////////////////////////
[238]446mapping_pseg_t *boot_pseg_get(unsigned int seg_id) 
447{
[228]448    mapping_header_t * header = (mapping_header_t *) & seg_mapping_base;
449    mapping_pseg_t * pseg = boot_get_pseg_base(header);
[189]450
451    // checking argument
[238]452    if (seg_id >= header->psegs) 
453    {
[189]454        boot_puts("\n[BOOT ERROR] : seg_id argument too large\n");
455        boot_puts("               in function boot_pseg_get()\n");
456        boot_exit();
457    }
458
[228]459    return &pseg[seg_id];
[238]460} 
[189]461
462//////////////////////////////////////////////////////////////////////////////
463// boot_add_pte()
[238]464// This function registers a new PTE in the page table defined
[189]465// by the vspace_id argument, and updates both PT1 and PT2.
466// A new PT2 is used when required.
467// As the set of PT2s is implemented as a fixed size array (no dynamic
468// allocation), this function checks a possible overflow of the PT2 array.
469//////////////////////////////////////////////////////////////////////////////
[228]470void boot_add_pte(unsigned int vspace_id,
[238]471                  unsigned int vpn, 
472                  unsigned int flags, 
473                  unsigned int ppn,
474                  unsigned int verbose) 
475{
[228]476    unsigned int ix1;
477    unsigned int ix2;
[238]478    paddr_t      pt1_pbase;     // PT1 physical base address
479    paddr_t      pt2_pbase;     // PT2 physical base address
480    paddr_t      pte_paddr;     // PTE physucal address
481    unsigned int pt2_id;        // PT2 index
482    unsigned int ptd;           // PTD : entry in PT1
483    unsigned int max_pt2;       // max number of PT2s for a given vspace
[189]484
[228]485    ix1 = vpn >> 9;         // 11 bits
486    ix2 = vpn & 0x1FF;      //  9 bits
[189]487
488    // check that the boot_max_pt2[vspace_id] has been set
[238]489    max_pt2 = boot_max_pt2[vspace_id];
[189]490
[238]491    if (max_pt2 == 0) 
492    {
493        boot_puts("Undefined page table for vspace ");
[204]494        boot_putd(vspace_id);
[189]495        boot_puts("\n");
496        boot_exit();
497    }
498
[246]499
[238]500    // get page table physical base address
501    pt1_pbase = boot_ptabs_paddr[vspace_id];
502
503    // get ptd in PT1
[246]504    ptd = boot_physical_read(pt1_pbase + 4 * ix1);
[238]505
506    if ((ptd & PTE_V) == 0)    // invalid PTD: compute PT2 base address,
507                               // and set a new PTD in PT1
508    {
[189]509        pt2_id = boot_next_free_pt2[vspace_id];
[238]510        if (pt2_id == max_pt2) 
511        {
[189]512            boot_puts("\n[BOOT ERROR] in boot_add_pte() function\n");
[228]513            boot_puts("the length of the ptab vobj is too small\n");
[249]514
515            boot_puts(" max_pt2 = ");
516            boot_putd( max_pt2 );
517            boot_puts("\n");
518            boot_puts(" pt2_id  = ");
519            boot_putd( pt2_id );
520            boot_puts("\n");
521           
[189]522            boot_exit();
523        }
[238]524        else 
525        {
526            pt2_pbase = pt1_pbase + PT1_SIZE + PT2_SIZE * pt2_id;
[246]527            ptd = PTE_V | PTE_T | (unsigned int) (pt2_pbase >> 12);
528            boot_physical_write( pt1_pbase + 4 * ix1, ptd);
[189]529            boot_next_free_pt2[vspace_id] = pt2_id + 1;
530        }
531    }
[238]532    else                       // valid PTD: compute PT2 base address
533    {
534        pt2_pbase = ((paddr_t)(ptd & 0x0FFFFFFF)) << 12;
[189]535    }
536
[238]537    // set PTE in PT2 : flags & PPN in two 32 bits words
[246]538    pte_paddr = pt2_pbase + 8 * ix2;
539    boot_physical_write(pte_paddr    , flags);
540    boot_physical_write(pte_paddr + 4, ppn);
[189]541
[246]542    if (verbose)
543    {
544        boot_puts("     / pt1_pbase = ");
545        boot_putl( pt1_pbase );
546        boot_puts(" / ptd = ");
547        boot_putl( ptd );
548        boot_puts(" / pt2_pbase = ");
549        boot_putl( pt2_pbase );
550        boot_puts(" / pte_paddr = ");
551        boot_putl( pte_paddr );
552        boot_puts(" / ppn = ");
553        boot_putx( ppn );
554        boot_puts("/\n");
555    }
[236]556
[238]557}   // end boot_add_pte()
[228]558
559
[189]560/////////////////////////////////////////////////////////////////////
[255]561// This function builds the page table for a given vspace.
[189]562// The physical base addresses for all vsegs (global and private)
[238]563// must have been previously computed and stored in the mapping.
[189]564// It initializes the MWMR channels.
565/////////////////////////////////////////////////////////////////////
[238]566void boot_vspace_pt_build(unsigned int vspace_id) 
567{
[228]568    unsigned int vseg_id;
569    unsigned int npages;
570    unsigned int ppn;
571    unsigned int vpn;
572    unsigned int flags;
573    unsigned int page_id;
[238]574    unsigned int verbose = 0;   // can be used to activate trace in add_pte()
[189]575
[228]576    mapping_header_t * header = (mapping_header_t *) & seg_mapping_base;
577    mapping_vspace_t * vspace = boot_get_vspace_base(header);
[238]578    mapping_vseg_t   * vseg   = boot_get_vseg_base(header);
[228]579
[189]580    // private segments
[228]581    for (vseg_id = vspace[vspace_id].vseg_offset;
[238]582         vseg_id < (vspace[vspace_id].vseg_offset + vspace[vspace_id].vsegs);
[255]583         vseg_id++)
[238]584    {
[228]585        vpn = vseg[vseg_id].vbase >> 12;
[246]586        ppn = (unsigned int) (vseg[vseg_id].pbase >> 12);
587
[228]588        npages = vseg[vseg_id].length >> 12;
[238]589        if ((vseg[vseg_id].length & 0xFFF) != 0) npages++; 
[189]590
591        flags = PTE_V;
[246]592        if (vseg[vseg_id].mode & C_MODE_MASK) flags = flags | PTE_C;
593        if (vseg[vseg_id].mode & X_MODE_MASK) flags = flags | PTE_X;
594        if (vseg[vseg_id].mode & W_MODE_MASK) flags = flags | PTE_W;
595        if (vseg[vseg_id].mode & U_MODE_MASK) flags = flags | PTE_U;
[189]596
597#if BOOT_DEBUG_PT
[228]598        boot_puts(vseg[vseg_id].name);
599        boot_puts(" : flags = ");
600        boot_putx(flags);
601        boot_puts(" / npages = ");
602        boot_putd(npages);
[255]603        boot_puts(" / vbase = ");
604        boot_putx(vseg[vseg_id].vbase);
[228]605        boot_puts(" / pbase = ");
[238]606        boot_putl(vseg[vseg_id].pbase);
[228]607        boot_puts("\n");
608#endif
[189]609        // loop on 4K pages
[238]610        for (page_id = 0; page_id < npages; page_id++) 
611        {
612            boot_add_pte(vspace_id, vpn, flags, ppn, verbose);
[189]613            vpn++;
614            ppn++;
615        }
616    }
617
618    // global segments
[238]619    for (vseg_id = 0; vseg_id < header->globals; vseg_id++) 
620    {
[228]621        vpn = vseg[vseg_id].vbase >> 12;
[255]622        ppn = (unsigned int) (vseg[vseg_id].pbase >> 12);
[228]623        npages = vseg[vseg_id].length >> 12;
[238]624        if ((vseg[vseg_id].length & 0xFFF) != 0) npages++;
[189]625
626        flags = PTE_V;
[238]627        if (vseg[vseg_id].mode & C_MODE_MASK)  flags = flags | PTE_C;
628        if (vseg[vseg_id].mode & X_MODE_MASK)  flags = flags | PTE_X;
629        if (vseg[vseg_id].mode & W_MODE_MASK)  flags = flags | PTE_W;
630        if (vseg[vseg_id].mode & U_MODE_MASK)  flags = flags | PTE_U;
[189]631
632#if BOOT_DEBUG_PT
[228]633        boot_puts(vseg[vseg_id].name);
[238]634        boot_puts(" : flags = ");
[228]635        boot_putx(flags);
636        boot_puts(" / npages = ");
637        boot_putd(npages);
[255]638        boot_puts(" / vbase = ");
639        boot_putx(vseg[vseg_id].vbase);
[228]640        boot_puts(" / pbase = ");
[238]641        boot_putl(vseg[vseg_id].pbase);
[228]642        boot_puts("\n");
643#endif
[189]644        // loop on 4K pages
[238]645        for (page_id = 0; page_id < npages; page_id++) 
646        {
647            boot_add_pte(vspace_id, vpn, flags, ppn, verbose);
[189]648            vpn++;
649            ppn++;
650        }
651    }
[238]652}   // end boot_vspace_pt_build()
[189]653
654
655///////////////////////////////////////////////////////////////////////////
[255]656// Aligns the value of paddr or vaddr to the required alignement,
[238]657// defined by alignPow2 == L2(alignement).
[189]658///////////////////////////////////////////////////////////////////////////
[238]659paddr_t paddr_align_to(paddr_t paddr, unsigned int alignPow2) 
660{
661    paddr_t mask = (1 << alignPow2) - 1;
662    return ((paddr + mask) & ~mask);
663}
664
665unsigned int vaddr_align_to(unsigned int vaddr, unsigned int alignPow2) 
666{
[228]667    unsigned int mask = (1 << alignPow2) - 1;
[238]668    return ((vaddr + mask) & ~mask);
[189]669}
670
[255]671
672
673///////////////////////////////////////////////////////////
674// Maps vseg on a pbase with identity mapping required
675// The pseg is already set
676// The length of the vseg must already be known
677///////////////////////////////////////////////////////////
678void boot_vseg_set_paddr_ident(mapping_vseg_t * vseg) {
679    unsigned int vseg_id;
680
681    mapping_header_t * header = (mapping_header_t *) & seg_mapping_base;
682    mapping_vseg_t * vseg_base = boot_get_vseg_base(header);
683 
684    if (vseg->pbase_set != 0) {
685        boot_puts("\n[BOOT ERROR] in boot_vseg_set_paddr() function (internal error):\n");
686        boot_puts("*** vseg->pbase already set\n");
687        boot_exit();
688    }
689
690    for (vseg_id = 0; vseg_id < header->vsegs; vseg_id++) {
691        // Already mapped vseg on the same pseg
692        if (vseg_base[vseg_id].psegid == vseg->psegid && vseg_base[vseg_id].pbase_set == 1) {
693            // Checking overlap condition
694            if (vseg->vbase == vseg_base[vseg_id].pbase || 
695                    ((vseg->vbase < vseg_base[vseg_id].pbase) && (vseg->vbase + vseg->length > vseg_base[vseg_id].pbase)) ||
696                    ((vseg->vbase > vseg_base[vseg_id].pbase) && (vseg_base[vseg_id].pbase + vseg_base[vseg_id].length > vseg->vbase))) {
697                boot_puts("\n[BOOT ERROR] in boot_vseg_set_paddr_ident() function\n");
698                boot_puts("*** Overlapping segments:\n");
699                boot_puts("    seg with base = ");
700                boot_putl(vseg->vbase);
701                boot_puts(" - length = ");
702                boot_putl(vseg->length);
703                boot_puts("\n");
704                boot_puts("    seg with base = \n");
705                boot_putl(vseg_base[vseg_id].vbase);
706                boot_puts(" - length = ");
707                boot_putl(vseg_base[vseg_id].length);
708                boot_puts("\n");
709                boot_exit();
710            }
711        }
712    }
713    vseg->pbase = vseg->vbase;
714    vseg->pbase_set = 1;
715}
716
717
718
719///////////////////////////////////////////////////////////
720// Maps vseg on a pbase with no identity mapping required
721// The pseg is already set
722// The length of the vseg must already be known
723///////////////////////////////////////////////////////////
724void boot_vseg_set_paddr(mapping_vseg_t * vseg) {
725    unsigned int vseg_id;
726    unsigned int nb_vsegs_mapped = 0;
727    unsigned int mapped = 0;
728    int i = 0;
729
730    paddr_t prev_base;
731    paddr_t prev_length = 0;
732    paddr_t curr_base = 0;
733    paddr_t curr_length = 0;
734    paddr_t next_base = 0;
735    paddr_t next_length = 0;
736
737    mapping_header_t * header = (mapping_header_t *) & seg_mapping_base;
738    mapping_vseg_t * vseg_base = boot_get_vseg_base(header);
739    mapping_vobj_t * vobj_base = boot_get_vobj_base(header);
740    mapping_pseg_t * pseg = boot_pseg_get(vseg->psegid);
741
742    const int align = max(vobj_base[vseg->vobj_offset].align, 12);
743
744    prev_base = pseg->base;
745 
746    if (vseg->pbase_set != 0) {
747        boot_puts("\n[BOOT ERROR] in boot_vseg_set_paddr() function (internal error):\n");
748        boot_puts("*** vseg->pbase already set\n");
749        boot_exit();
750    }
751
752    // We now determinine the physical base address of the vseg
753    // Method:
754    // Now that all identity segments have been mapped
755    // We are free to place the vseg where we want
756    // From a logical point of view, we have the list of mapped vsegs ordered by their pbase (increasing)
757    // We try to place the vseg between two consecutive elements of this list
758    // If this fails, we try between the next two mapped vsegs
759
760    // Counting the number of vsegs mapped on this pseg
761    // We also initialize curr_base and curr_length with some values
762    for (vseg_id = 0; vseg_id < header->vsegs; vseg_id++) {
763        if (vseg_base[vseg_id].psegid == vseg->psegid && vseg_base[vseg_id].pbase_set == 1) {
764           nb_vsegs_mapped++;
765           curr_base = vseg_base[vseg_id].pbase;
766           curr_length = vseg_base[vseg_id].length;
767        }
768    }
769
770    if (nb_vsegs_mapped == 0) {
771        if (vseg->length <= pseg->length) {
772            vseg->pbase = pseg->base;
773            vseg->pbase_set = 1;
774            return;
775        }
776        else {
777            boot_puts("\n[BOOT ERROR] in boot_vseg_set_paddr() function\n");
778            boot_puts("*** PSEG is too small for mapping vseg (base:");
779            boot_putl(vseg->vbase);
780            boot_puts(" - length: ");
781            boot_putl(vseg->length);
782            boot_puts(")\n");
783            boot_exit();
784        }
785    }
786
787    // We look for the vseg mapped on the same pseg having the smallest vaddr
788    for (vseg_id = 0; vseg_id < header->vsegs; vseg_id++) {
789        if (vseg_base[vseg_id].psegid == vseg->psegid
790                && &vseg_base[vseg_id] != vseg
791                && vseg_base[vseg_id].pbase_set == 1
792                && vseg_base[vseg_id].pbase < curr_base) {
793            curr_base = vseg_base[vseg_id].pbase;
794            curr_length = vseg_base[vseg_id].length;           
795        }
796    }
797
798    // We iterate on each vseg mapped in the order of their growing pbase
799    // and try to insert the current vseg right after each
800    while (i < nb_vsegs_mapped) {
801        if (paddr_align_to(prev_base + prev_length, align) + vseg->length <= curr_base) {
802            vseg->pbase = paddr_align_to(prev_base + prev_length, align);
803            vseg->pbase_set = 1;
804            mapped = 1;
805            break;
806        }
807        else if (i < nb_vsegs_mapped - 1) {
808            int found = 0;
809            next_base = 0;
810            // We search for the vseg having the minimal pbase which is more than the pbase of the current vseg
811            for (vseg_id = 0; vseg_id < header->vsegs; vseg_id++) {
812                if (vseg_base[vseg_id].psegid == vseg->psegid
813                        && &vseg_base[vseg_id] != vseg
814                        && vseg_base[vseg_id].pbase_set == 1
815                        && (vseg_base[vseg_id].pbase < next_base || !found)
816                        && vseg_base[vseg_id].pbase > curr_base) {
817                    found = 1;
818                    next_base = vseg_base[vseg_id].pbase;
819                    next_length = vseg_base[vseg_id].length;
820                }
821            }
822            if (!found) {
823                boot_puts("\n[BOOT ERROR] in boot_vseg_set_paddr() function (internal error):\n");
824                boot_puts("*** Next vseg not found\n");
825                boot_exit();
826            }
827
828            prev_base = curr_base;
829            prev_length = curr_length;
830
831            curr_base = next_base;
832            curr_length = next_length;
833        }
834        else {
835            // The current vseg is the last one (highest mapped paddr on this pseg)
836            // We try to insert the current vseg after it
837            if (paddr_align_to(curr_base + curr_length, align) + vseg->length <= pseg->base + pseg->length) {
838                vseg->pbase = paddr_align_to(curr_base + curr_length, align);
839                vseg->pbase_set = 1;
840                mapped = 1;
841            }
842        }
843        i++;
844    }
845
846    if (!mapped) {
847        boot_puts("\n[BOOT ERROR] in boot_vseg_set_paddr() function:\n");
848        boot_puts("*** Not enough space to map vseg (base: ");
849        boot_putl(vseg->vbase);
850        boot_puts(" - length: ");
851        boot_putl(vseg->length);
852        boot_puts(")\n");
853        boot_exit();
854    }
855}
856
857
[189]858///////////////////////////////////////////////////////////////////////////
[238]859// This function computes the physical base address for a vseg
[189]860// as specified in the mapping info data structure.
861// It updates the pbase and the length fields of the vseg.
862// It updates the pbase and vbase fields of all vobjs in the vseg.
863// It updates the boot_ptabs_paddr[] and boot_ptabs_vaddr[] arrays.
864// It is a global vseg if vspace_id = (-1).
865///////////////////////////////////////////////////////////////////////////
[238]866void boot_vseg_map(mapping_vseg_t * vseg, unsigned int vspace_id) 
867{
[228]868    unsigned int vobj_id;
869    unsigned int cur_vaddr;
[238]870    paddr_t      cur_paddr;
[255]871    paddr_t      cur_length;
[238]872    unsigned int offset;
873
[228]874    mapping_header_t * header = (mapping_header_t *) & seg_mapping_base;
[255]875    mapping_vobj_t * vobj = boot_get_vobj_base(header);
[228]876
[255]877    // We make a first loop on the vobj of the vseg to determine the real length of the vseg
878    // This length is required to determine the pbase of the vseg
879    cur_length = 0;
880    for (vobj_id = vseg->vobj_offset; vobj_id < (vseg->vobj_offset + vseg->vobjs); vobj_id++) {
881        if (vobj[vobj_id].align) {
882            cur_length = vaddr_align_to(cur_length, vobj[vobj_id].align);
883        }
884        cur_length += vobj[vobj_id].length;
[189]885    }
[255]886    vseg->length = paddr_align_to(cur_length, 12);
[189]887
[255]888    // We can now compute the vseg physical base address
889    if (vseg->ident != 0) { 
890        // identity mapping required
891        boot_vseg_set_paddr_ident(vseg);
[189]892    }
[255]893    else {
894        // unconstrained mapping
895        boot_vseg_set_paddr(vseg);
896    }
[228]897
[255]898
[189]899    // loop on vobjs contained in vseg to :
900    // (1) computes the length of the vseg,
[230]901    // (2) initialize the vaddr and paddr fields of all vobjs,
[255]902    // (3) initialize the page table pointers arrays
[189]903
904    cur_vaddr = vseg->vbase;
905    cur_paddr = vseg->pbase;
906
[255]907    for (vobj_id = vseg->vobj_offset;
908         vobj_id < (vseg->vobj_offset + vseg->vobjs); vobj_id++) {
909        if (vobj[vobj_id].align) {
[238]910            cur_paddr = paddr_align_to(cur_paddr, vobj[vobj_id].align);
911            cur_vaddr = vaddr_align_to(cur_vaddr, vobj[vobj_id].align);
[189]912        }
[228]913        // set vaddr/paddr for current vobj
914        vobj[vobj_id].vaddr = cur_vaddr;
915        vobj[vobj_id].paddr = cur_paddr;
[230]916       
[246]917        // initialize boot_ptabs_vaddr[] & boot_ptabs-paddr[] if PTAB
[238]918        if (vobj[vobj_id].type == VOBJ_TYPE_PTAB) 
919        {
920            if (vspace_id == ((unsigned int) -1))    // global vseg
921            {
[228]922                boot_puts("\n[BOOT ERROR] in boot_vseg_map() function: ");
923                boot_puts("a PTAB vobj cannot be global");
[189]924                boot_exit();
925            }
[238]926            // we need at least one PT2
[255]927            if (vobj[vobj_id].length < (PT1_SIZE + PT2_SIZE))
[238]928            {
[228]929                boot_puts("\n[BOOT ERROR] in boot_vseg_map() function, ");
[189]930                boot_puts("PTAB too small, minumum size is: ");
[228]931                boot_putx(PT1_SIZE + PT2_SIZE);
[189]932                boot_exit();
933            }
934            // register both physical and virtual page table address
[238]935            boot_ptabs_vaddr[vspace_id] = vobj[vobj_id].vaddr;
936            boot_ptabs_paddr[vspace_id] = vobj[vobj_id].paddr;
[246]937           
[238]938            // reset all valid bits in PT1
[255]939            for (offset = 0; offset < 8192; offset = offset + 4)
[238]940            {
[246]941                boot_physical_write(cur_paddr + offset, 0);
[238]942            }
943
944            // computing the number of second level pages
[189]945            boot_max_pt2[vspace_id] = (vobj[vobj_id].length - PT1_SIZE) / PT2_SIZE;
946        }
[238]947
[189]948        // set next vaddr/paddr
[238]949        cur_vaddr = cur_vaddr + vobj[vobj_id].length;
950        cur_paddr = cur_paddr + vobj[vobj_id].length;
[189]951    } // end for vobjs
[228]952
[189]953#if BOOT_DEBUG_PT
[228]954    boot_puts(vseg->name);
955    boot_puts(" : len = ");
956    boot_putx(vseg->length);
957    boot_puts(" / vbase = ");
958    boot_putx(vseg->vbase);
959    boot_puts(" / pbase = ");
[238]960    boot_putl(vseg->pbase);
[228]961    boot_puts("\n");
962#endif
[189]963
[238]964}    // end boot_vseg_map()
[210]965
[189]966/////////////////////////////////////////////////////////////////////
967// This function checks consistence beween the  mapping_info data
968// structure (soft), and the giet_config file (hard).
969/////////////////////////////////////////////////////////////////////
[238]970void boot_check_mapping() 
971{
[228]972    mapping_header_t * header = (mapping_header_t *) & seg_mapping_base;
[189]973
974    // checking mapping availability
[238]975    if (header->signature != IN_MAPPING_SIGNATURE) 
976    {
[189]977        boot_puts("\n[BOOT ERROR] Illegal mapping signature: ");
[204]978        boot_putx(header->signature);
[189]979        boot_puts("\n");
980        boot_exit();
981    }
[203]982    // checking number of clusters
[238]983    if (header->clusters != NB_CLUSTERS) 
984    {
[189]985        boot_puts("\n[BOOT ERROR] Incoherent NB_CLUSTERS");
986        boot_puts("\n             - In giet_config,  value = ");
[228]987        boot_putd(NB_CLUSTERS);
[189]988        boot_puts("\n             - In mapping_info, value = ");
[228]989        boot_putd(header->clusters);
[189]990        boot_puts("\n");
991        boot_exit();
992    }
[199]993    // checking number of virtual spaces
[238]994    if (header->vspaces > GIET_NB_VSPACE_MAX) 
995    {
[199]996        boot_puts("\n[BOOT ERROR] : number of vspaces > GIET_NB_VSPACE_MAX\n");
997        boot_puts("\n");
998        boot_exit();
999    }
[189]1000
[253]1001#if BOOT_DEBUG_MAPPING
[255]1002    boot_puts("\nclusters  = ");
1003    boot_putd( header->clusters );
1004    boot_puts("\nprocs     = ");
1005    boot_putd( header->procs );
1006    boot_puts("\nperiphs   = ");
1007    boot_putd( header->periphs );
1008    boot_puts("\nvspaces   = ");
1009    boot_putd( header->vspaces );
1010    boot_puts("\ntasks     = ");
1011    boot_putd( header->tasks );
1012    boot_puts("\n");
[253]1013
[255]1014    unsigned int        cluster_id;
1015    mapping_cluster_t * cluster = boot_get_cluster_base(header);
1016    for (cluster_id = 0; cluster_id < NB_CLUSTERS; cluster_id++) 
1017    {
1018        boot_puts("\n cluster = ");
1019        boot_putd( cluster_id );
1020        boot_puts("\n procs   = ");
1021        boot_putd( cluster[cluster_id].procs );
1022        boot_puts("\n psegs   = ");
1023        boot_putd( cluster[cluster_id].psegs );
1024        boot_puts("\n periphs = ");
1025        boot_putd( cluster[cluster_id].periphs );
1026        boot_puts("\n");
1027    }
[253]1028#endif
1029
1030    boot_puts("\n[BOOT] Mapping check completed at cycle ");
1031    boot_putd(boot_proctime());
1032    boot_puts(" for ");
1033    boot_puts( header->name );
1034    boot_puts("\n");
1035
[189]1036} // end boot_check_mapping()
1037
1038
1039/////////////////////////////////////////////////////////////////////
1040// This function builds the page tables for all virtual spaces
[238]1041// defined in the mapping_info data structure, in three steps:
1042// - step 1 : It computes the physical base address for global vsegs
1043//            and for all associated vobjs.
1044// - step 2 : It computes the physical base address for all private
1045//            vsegs and all vobjs in each virtual space.
1046// - step 3 : It actually fill the page table for each vspace.
[189]1047/////////////////////////////////////////////////////////////////////
[238]1048void boot_pt_init() 
1049{
[228]1050    mapping_header_t * header = (mapping_header_t *) &seg_mapping_base;
1051    mapping_vspace_t * vspace = boot_get_vspace_base(header);
[238]1052    mapping_vseg_t   * vseg   = boot_get_vseg_base(header);
[189]1053
[228]1054    unsigned int vspace_id;
1055    unsigned int vseg_id;
[189]1056
1057#if BOOT_DEBUG_PT
[255]1058    boot_puts("\n[BOOT DEBUG] ****** mapping global vsegs ******\n");
[189]1059#endif
[228]1060
[238]1061    // step 1 : loop on virtual spaces to map global vsegs
[255]1062    // Identity vseg first
[238]1063    for (vseg_id = 0; vseg_id < header->globals; vseg_id++) 
1064    {
[255]1065        if (vseg[vseg_id].ident == 1) {
1066            boot_vseg_map(&vseg[vseg_id], ((unsigned int) (-1)));
1067        }
[189]1068    }
[255]1069    // Non identity vseg second
1070    for (vseg_id = 0; vseg_id < header->globals; vseg_id++) 
1071    {
1072        if (vseg[vseg_id].ident == 0) {
1073            boot_vseg_map(&vseg[vseg_id], ((unsigned int) (-1)));
1074        }
1075    }
[189]1076
[255]1077
[189]1078    // step 2 : loop on virtual vspaces to map private vsegs
[238]1079    for (vspace_id = 0; vspace_id < header->vspaces; vspace_id++) 
1080    {
[189]1081
1082#if BOOT_DEBUG_PT
[255]1083        boot_puts("\n[BOOT DEBUG] ****** mapping private vsegs in vspace ");
1084        boot_puts(vspace[vspace_id].name);
1085        boot_puts(" ******\n");
[189]1086#endif
[228]1087
[255]1088        // Identity vseg first
[228]1089        for (vseg_id = vspace[vspace_id].vseg_offset;
[246]1090             vseg_id < (vspace[vspace_id].vseg_offset + vspace[vspace_id].vsegs);
[255]1091             vseg_id++) {
1092            if (vseg[vseg_id].ident == 1) {
1093                boot_vseg_map(&vseg[vseg_id], vspace_id);
1094            }
[189]1095        }
[255]1096        // Non identity vseg second
1097        for (vseg_id = vspace[vspace_id].vseg_offset;
1098             vseg_id < (vspace[vspace_id].vseg_offset + vspace[vspace_id].vsegs);
1099             vseg_id++) {
1100            if (vseg[vseg_id].ident == 0) {
1101                boot_vseg_map(&vseg[vseg_id], vspace_id);
1102            }
1103        }
[228]1104    }
[189]1105
1106    // step 3 : loop on the vspaces to build the page tables
[238]1107    for (vspace_id = 0; vspace_id < header->vspaces; vspace_id++) 
1108    {
[189]1109#if BOOT_DEBUG_PT
[255]1110        boot_puts("\n[BOOT DEBUG] ****** building page table for vspace ");
1111        boot_puts(vspace[vspace_id].name);
1112        boot_puts(" ******\n");
[189]1113#endif
[255]1114
[228]1115        boot_vspace_pt_build(vspace_id);
1116
[189]1117#if BOOT_DEBUG_PT
[255]1118        boot_puts("\n>>> page table physical address = ");
1119        boot_putl(boot_ptabs_paddr[vspace_id]);
1120        boot_puts(", number of PT2 = ");
1121        boot_putd((unsigned int) boot_max_pt2[vspace_id]);
1122        boot_puts("\n");
[189]1123#endif
[228]1124    }
[253]1125
[255]1126    boot_puts("\n[BOOT] Page Tables initialization completed at cycle ");
[253]1127    boot_putd(boot_proctime());
1128    boot_puts("\n");
1129
[189]1130} // end boot_pt_init()
1131
1132///////////////////////////////////////////////////////////////////////////////
1133// This function initializes all private vobjs defined in the vspaces,
1134// such as mwmr channels, barriers and locks, because these vobjs
[228]1135// are not known, and not initialized by the compiler.
[238]1136// Warning : The MMU is supposed to be activated...
[189]1137///////////////////////////////////////////////////////////////////////////////
[255]1138void boot_vobjs_init()
[238]1139{
1140    mapping_header_t* header = (mapping_header_t *) & seg_mapping_base;
1141    mapping_vspace_t* vspace = boot_get_vspace_base(header);
1142    mapping_vobj_t* vobj     = boot_get_vobj_base(header);
[189]1143
[228]1144    unsigned int vspace_id;
1145    unsigned int vobj_id;
[189]1146
[238]1147    // loop on the vspaces
1148    for (vspace_id = 0; vspace_id < header->vspaces; vspace_id++) 
1149    {
[255]1150        boot_set_mmu_ptpr((unsigned int) (boot_ptabs_paddr[vspace_id] >> 13));
[189]1151
1152#if BOOT_DEBUG_VOBJS
[255]1153        boot_puts("\n[BOOT DEBUG] ****** vobjs initialisation in vspace ");
1154        boot_puts(vspace[vspace_id].name);
1155        boot_puts(" ******\n");
[189]1156#endif
1157
1158        unsigned int ptab_found = 0;
1159
1160        // loop on the vobjs
[228]1161        for (vobj_id = vspace[vspace_id].vobj_offset;
[238]1162             vobj_id < (vspace[vspace_id].vobj_offset + vspace[vspace_id].vobjs);
[255]1163             vobj_id++)
[238]1164        {
1165            switch (vobj[vobj_id].type) 
1166            {
[228]1167                case VOBJ_TYPE_MWMR:    // storage capacity is (vobj.length/4 - 5) words
1168                {
[238]1169                    mwmr_channel_t* mwmr = (mwmr_channel_t *) (vobj[vobj_id].vaddr);
[228]1170                    mwmr->ptw = 0;
1171                    mwmr->ptr = 0;
1172                    mwmr->sts = 0;
[189]1173                    mwmr->width = vobj[vobj_id].init;
[228]1174                    mwmr->depth = (vobj[vobj_id].length >> 2) - 6;
1175                    mwmr->lock = 0;
[189]1176#if BOOT_DEBUG_VOBJS
[255]1177                    boot_puts("MWMR    : ");
1178                    boot_puts(vobj[vobj_id].name);
1179                    boot_puts(" / depth = ");
1180                    boot_putd(mwmr->depth);
1181                    boot_puts(" / width = ");
1182                    boot_putd(mwmr->width);
1183                    boot_puts("\n");
[189]1184#endif
1185                    break;
1186                }
[228]1187                case VOBJ_TYPE_ELF:    // initialisation done by the loader
[189]1188                {
1189#if BOOT_DEBUG_VOBJS
[255]1190                    boot_puts("ELF     : ");
1191                    boot_puts(vobj[vobj_id].name);
1192                    boot_puts(" / length = ");
1193                    boot_putx(vobj[vobj_id].length);
1194                    boot_puts("\n");
[189]1195#endif
1196                    break;
1197                }
[228]1198                case VOBJ_TYPE_BLOB:    // initialisation done by the loader
[189]1199                {
1200#if BOOT_DEBUG_VOBJS
[255]1201                    boot_puts("BLOB     : ");
1202                    boot_puts(vobj[vobj_id].name);
1203                    boot_puts(" / length = ");
1204                    boot_putx(vobj[vobj_id].length);
1205                    boot_puts("\n");
[189]1206#endif
1207                    break;
1208                }
[228]1209                case VOBJ_TYPE_BARRIER:    // init is the number of participants
[189]1210                {
[238]1211                    giet_barrier_t* barrier = (giet_barrier_t *) (vobj[vobj_id].vaddr);
[228]1212                    barrier->count = vobj[vobj_id].init;
1213                    barrier->init = vobj[vobj_id].init;
[189]1214#if BOOT_DEBUG_VOBJS
[255]1215                    boot_puts("BARRIER : ");
1216                    boot_puts(vobj[vobj_id].name);
1217                    boot_puts(" / init_value = ");
1218                    boot_putd(barrier->init);
1219                    boot_puts("\n");
[189]1220#endif
1221                    break;
1222                }
[238]1223                case VOBJ_TYPE_LOCK:    // init value is "not taken"
[189]1224                {
[238]1225                    unsigned int* lock = (unsigned int *) (vobj[vobj_id].vaddr);
[189]1226                    *lock = 0;
1227#if BOOT_DEBUG_VOBJS
[255]1228                    boot_puts("LOCK    : ");
1229                    boot_puts(vobj[vobj_id].name);
1230                    boot_puts("\n");
[189]1231#endif
1232                    break;
1233                }
[228]1234                case VOBJ_TYPE_BUFFER:    // nothing to initialise
[189]1235                {
1236#if BOOT_DEBUG_VOBJS
[255]1237                    boot_puts("BUFFER  : ");
1238                    boot_puts(vobj[vobj_id].name);
1239                    boot_puts(" / paddr = ");
1240                    boot_putl(vobj[vobj_id].paddr);
1241                    boot_puts(" / length = ");
1242                    boot_putx(vobj[vobj_id].length);
1243                    boot_puts("\n");
[189]1244#endif
1245                    break;
1246                }
[228]1247                case VOBJ_TYPE_MEMSPACE:
[189]1248                {
[255]1249                    giet_memspace_t * memspace = (giet_memspace_t *) vobj[vobj_id].vaddr;
[228]1250                    memspace->buffer = (void *) vobj[vobj_id].vaddr + 8;
1251                    memspace->size = vobj[vobj_id].length - 8;
1252#if BOOT_DEBUG_VOBJS
[255]1253                    boot_puts("MEMSPACE  : ");
1254                    boot_puts(vobj[vobj_id].name);
1255                    boot_puts(" / vaddr = ");
1256                    boot_putx(vobj[vobj_id].vaddr);
1257                    boot_puts(" / length = ");
1258                    boot_putx(vobj[vobj_id].length);
1259                    boot_puts(" / buffer = ");
1260                    boot_putx((unsigned int) memspace->buffer);
1261                    boot_puts(" / size = ");
1262                    boot_putx(memspace->size);
1263                    boot_puts("\n");
[228]1264#endif
1265                    break;
1266                }
[230]1267                case VOBJ_TYPE_PTAB:    // nothing to initialize
[228]1268                {
[189]1269                    ptab_found = 1;
1270#if BOOT_DEBUG_VOBJS
[255]1271                    boot_puts("PTAB    : ");
1272                    boot_puts(vobj[vobj_id].name);
1273                    boot_puts(" / length = ");
1274                    boot_putx(vobj[vobj_id].length);
1275                    boot_puts("\n");
[189]1276#endif
1277                    break;
1278                }
[228]1279                case VOBJ_TYPE_CONST:
1280                {
[238]1281                    unsigned int* addr = (unsigned int *) vobj[vobj_id].vaddr;
[230]1282                    *addr = vobj[vobj_id].init;
[228]1283#if BOOT_DEBUG_VOBJS
[255]1284                    boot_puts("CONST   : ");
1285                    boot_puts(vobj[vobj_id].name);
1286                    boot_puts(" / Paddr :");
1287                    boot_putl(vobj[vobj_id].paddr);
1288                    boot_puts(" / init = ");
1289                    boot_putx(*addr);
1290                    boot_puts("\n");
[228]1291#endif
1292                    break;
1293                }
[189]1294                default:
1295                {
[238]1296                    boot_puts("\n[BOOT ERROR] illegal vobj type: ");
[228]1297                    boot_putd(vobj[vobj_id].type);
[230]1298                    boot_puts("\n");
[189]1299                    boot_exit();
1300                }
[228]1301            }            // end switch type
1302        }            // end loop on vobjs
[238]1303        if (ptab_found == 0) 
1304        {
1305            boot_puts("\n[BOOT ERROR] Missing PTAB for vspace ");
[228]1306            boot_putd(vspace_id);
[189]1307            boot_exit();
1308        }
1309    } // end loop on vspaces
[253]1310
1311    boot_puts("\n[BOOT] Vobjs initialisation completed at cycle : ");
1312    boot_putd(boot_proctime());
1313    boot_puts("\n");
1314
[189]1315} // end boot_vobjs_init()
1316
[238]1317////////////////////////////////////////////////////////////////////////////////
1318// This function initializes one MWMR controller channel.
1319// - coproc_pbase  : physical base address of the Coproc configuration segment
1320// - channel_pbase : physical base address of the MWMR channel segment
1321// Warning : the channel physical base address should be on 32 bits, as the
1322// MWMR controller configuration registers are 32 bits.
1323// TODO : Introduce a MWMR_CONFIG_PADDR_EXT register in the MWMR coprocessor
1324//        To support addresses > 32 bits and remove this limitation...
1325///////////////////////////////////////////////////////////////////////////////
1326void mwmr_hw_init(paddr_t                coproc_pbase, 
1327                  enum mwmrPortDirection way,
1328                  unsigned int           no, 
1329                  paddr_t                channel_pbase) 
1330{
1331    if ( (channel_pbase>>32) != 0 )
1332    {
1333        boot_puts("\n[BOOT ERROR] MWMR controller does not support address > 32 bits\n");
1334        boot_exit();
1335    }
[228]1336
[238]1337    unsigned int lsb = (unsigned int)channel_pbase;
1338//  unsigned int msb = (unsigned int)(channel_pbase>>32);
[228]1339
[238]1340    unsigned int depth = boot_physical_read( channel_pbase + 16 );
1341    unsigned int width = boot_physical_read( channel_pbase + 20 );
1342
1343    boot_physical_write( coproc_pbase + MWMR_CONFIG_FIFO_WAY*4, way );
1344    boot_physical_write( coproc_pbase + MWMR_CONFIG_FIFO_NO*4, no );
1345    boot_physical_write( coproc_pbase + MWMR_CONFIG_WIDTH*4, width);
1346    boot_physical_write( coproc_pbase + MWMR_CONFIG_DEPTH*4, depth);
1347    boot_physical_write( coproc_pbase + MWMR_CONFIG_STATUS_ADDR*4, lsb);
1348    boot_physical_write( coproc_pbase + MWMR_CONFIG_BUFFER_ADDR*4, lsb + 24 );
1349//  boot_physical_write( coproc_pbase + MWMR_CONFIG_PADDR_EXT*4, msb);
1350    boot_physical_write( coproc_pbase + MWMR_CONFIG_RUNNING*4, 1 );
[200]1351}
1352
[189]1353////////////////////////////////////////////////////////////////////////////////
1354// This function intializes the periherals and coprocessors, as specified
[203]1355// in the mapping_info file.
[189]1356////////////////////////////////////////////////////////////////////////////////
[238]1357void boot_peripherals_init() 
1358{
[228]1359    mapping_header_t * header = (mapping_header_t *) & seg_mapping_base;
1360    mapping_cluster_t * cluster = boot_get_cluster_base(header);
1361    mapping_periph_t * periph = boot_get_periph_base(header);
1362    mapping_pseg_t * pseg = boot_get_pseg_base(header);
1363    mapping_vobj_t * vobj = boot_get_vobj_base(header);
1364    mapping_vspace_t * vspace = boot_get_vspace_base(header);
1365    mapping_coproc_t * coproc = boot_get_coproc_base(header);
1366    mapping_cp_port_t * cp_port = boot_get_cp_port_base(header);
[189]1367
[228]1368    unsigned int cluster_id;
1369    unsigned int periph_id;
1370    unsigned int coproc_id;
1371    unsigned int cp_port_id;
1372    unsigned int channel_id;
[189]1373
[238]1374    for (cluster_id = 0; cluster_id < header->clusters; cluster_id++) 
1375    {
[189]1376
1377#if BOOT_DEBUG_PERI
[255]1378        boot_puts("\n[BOOT DEBUG] ****** peripherals initialisation in cluster ");
1379        boot_putd(cluster_id);
1380        boot_puts(" ******\n");
[189]1381#endif
1382
[228]1383        for (periph_id = cluster[cluster_id].periph_offset;
[238]1384             periph_id < cluster[cluster_id].periph_offset +
1385             cluster[cluster_id].periphs; periph_id++) 
1386        {
[228]1387            unsigned int type = periph[periph_id].type;
1388            unsigned int channels = periph[periph_id].channels;
1389            unsigned int pseg_id = periph[periph_id].psegid;
[189]1390
[238]1391            paddr_t pbase = pseg[pseg_id].base;
[189]1392
1393#if BOOT_DEBUG_PERI
[255]1394            boot_puts("- peripheral type : ");
1395            boot_putd(type);
1396            boot_puts(" / pbase = ");
1397            boot_putl(pbase);
1398            boot_puts(" / channels = ");
1399            boot_putd(channels);
1400            boot_puts("\n");
[189]1401#endif
1402
[238]1403            switch (type) 
1404            {
[228]1405                case PERIPH_TYPE_IOC:    // vci_block_device component
[238]1406                {
1407                    paddr_t paddr = pbase + BLOCK_DEVICE_IRQ_ENABLE*4;
1408                    boot_physical_write(paddr, 1);
[189]1409#if BOOT_DEBUG_PERI
[255]1410                    boot_puts("- IOC initialised\n");
[189]1411#endif
[238]1412                }
1413                break;
[228]1414                case PERIPH_TYPE_DMA:    // vci_multi_dma component
[238]1415                    for (channel_id = 0; channel_id < channels; channel_id++) 
1416                    {
1417                        paddr_t paddr = pbase + (channel_id*DMA_SPAN + DMA_IRQ_DISABLE) * 4;
1418                        boot_physical_write(paddr, 0);
[218]1419                    }
[189]1420#if BOOT_DEBUG_PERI
[255]1421                    boot_puts("- DMA initialised\n");
[189]1422#endif
[238]1423                break;
[228]1424                case PERIPH_TYPE_NIC:    // vci_multi_nic component
[238]1425                    for (channel_id = 0; channel_id < channels; channel_id++) 
1426                    {
[218]1427                        // TODO
1428                    }
1429#if BOOT_DEBUG_PERI
[255]1430                    boot_puts("- NIC initialised\n");
[218]1431#endif
[238]1432                break;
[228]1433                case PERIPH_TYPE_TTY:    // vci_multi_tty component
[218]1434#if BOOT_DEBUG_PERI
[255]1435                boot_puts("- TTY initialised\n");
[218]1436#endif
[238]1437                break;
[228]1438                case PERIPH_TYPE_IOB:    // vci_io_bridge component
[249]1439                    if (USE_IOB) 
[238]1440                    {
[218]1441                        // TODO
1442                        // get the iommu page table physical address
1443                        // define IPI address mapping the IOC interrupt
1444                        // set IOMMU page table address
1445                        // pseg_base[IOB_IOMMU_PTPR] = ptab_pbase;   
1446                        // activate IOMMU
1447                        // pseg_base[IOB_IOMMU_ACTIVE] = 1;       
1448                    }
1449#if BOOT_DEBUG_PERI
[255]1450                    boot_puts("- IOB initialised\n");
[218]1451#endif
[238]1452                break;
1453            }  // end switch periph type
1454        }  // end for periphs
[189]1455
1456#if BOOT_DEBUG_PERI
[255]1457        boot_puts("\n[BOOT DEBUG] ****** coprocessors initialisation in cluster ");
1458        boot_putd(cluster_id);
1459        boot_puts(" ******\n");
[189]1460#endif
1461
[228]1462        for (coproc_id = cluster[cluster_id].coproc_offset;
[238]1463             coproc_id < cluster[cluster_id].coproc_offset +
1464             cluster[cluster_id].coprocs; coproc_id++) 
1465        {
1466            unsigned no_fifo_to = 0;    //FIXME: should the map.xml define the order?
[200]1467            unsigned no_fifo_from = 0;
1468
[238]1469            // Get physical base address for MWMR controler
1470            paddr_t coproc_pbase = pseg[coproc[coproc_id].psegid].base;
1471
[200]1472#if BOOT_DEBUG_PERI
[255]1473            boot_puts("- coprocessor name : ");
1474            boot_puts(coproc[coproc_id].name);
1475            boot_puts(" / nb ports = ");
1476            boot_putd((unsigned int) coproc[coproc_id].ports);
1477            boot_puts("\n");
[200]1478#endif
1479
[228]1480            for (cp_port_id = coproc[coproc_id].port_offset;
[238]1481                 cp_port_id < coproc[coproc_id].port_offset + coproc[coproc_id].ports;
1482                 cp_port_id++) 
1483            {
[228]1484                unsigned int vspace_id = cp_port[cp_port_id].vspaceid;
[238]1485                unsigned int vobj_id = cp_port[cp_port_id].mwmr_vobjid + 
1486                                          vspace[vspace_id].vobj_offset;
[200]1487
[238]1488                // Get MWMR channel base address
1489                paddr_t channel_pbase = vobj[vobj_id].paddr;
[200]1490
[238]1491                if (cp_port[cp_port_id].direction == PORT_TO_COPROC) 
1492                {
[200]1493#if BOOT_DEBUG_PERI
[255]1494                    boot_puts("     port direction: PORT_TO_COPROC");
[200]1495#endif
[238]1496                    mwmr_hw_init(coproc_pbase, 
1497                                 PORT_TO_COPROC, 
1498                                 no_fifo_to, 
1499                                 channel_pbase);
[200]1500                    no_fifo_to++;
1501                }
[238]1502                else 
1503                {
[200]1504#if BOOT_DEBUG_PERI
[255]1505                    boot_puts("     port direction: PORT_FROM_COPROC");
[200]1506#endif
[238]1507                    mwmr_hw_init(coproc_pbase, 
1508                                 PORT_FROM_COPROC, 
1509                                 no_fifo_from, 
1510                                 channel_pbase);
[200]1511                    no_fifo_from++;
1512                }
1513#if BOOT_DEBUG_PERI
[255]1514                boot_puts(", with mwmr: ");
1515                boot_puts(vobj[vobj_id].name);
1516                boot_puts(" of vspace: ");
1517                boot_puts(vspace[vspace_id].name);
[200]1518#endif
[238]1519            } // end for cp_ports
[189]1520        } // end for coprocs
1521    } // end for clusters
[253]1522
1523    boot_puts("\n[BOOT] Peripherals initialisation completed at cycle ");
1524    boot_putd(boot_proctime());
1525    boot_puts("\n");
1526
[189]1527} // end boot_peripherals_init()
1528
[238]1529///////////////////////////////////////////////////////////////////////////////
1530// This function returns in the vbase and length buffers the virtual base
1531// address and the length of the  segment allocated to the schedulers array
1532// in the cluster defined by the clusterid argument.
1533///////////////////////////////////////////////////////////////////////////////
1534void boot_get_sched_vaddr( unsigned int  cluster_id,
1535                           unsigned int* vbase, 
1536                           unsigned int* length )
1537{
1538    mapping_header_t* header = (mapping_header_t *) & seg_mapping_base;
1539    mapping_vobj_t*   vobj   = boot_get_vobj_base(header);
1540    mapping_vseg_t*   vseg   = boot_get_vseg_base(header);
1541    mapping_pseg_t*   pseg   = boot_get_pseg_base(header);
[189]1542
[238]1543    unsigned int vseg_id;
1544    unsigned int found = 0;
1545
1546    for ( vseg_id = 0 ; (vseg_id < header->vsegs) && (found == 0) ; vseg_id++ )
1547    {
1548        if ( (vobj[vseg[vseg_id].vobj_offset].type == VOBJ_TYPE_SCHED) && 
1549             (pseg[vseg[vseg_id].psegid].cluster == cluster_id ) )
1550        {
1551            *vbase  = vseg[vseg_id].vbase;
1552            *length = vobj[vseg[vseg_id].vobj_offset].length;
1553            found = 1;
1554        }
1555    }
1556    if ( found == 0 )
1557    {
1558        boot_puts("\n[BOOT ERROR] No vobj of type SCHED in cluster ");
1559        boot_putd(cluster_id);
1560        boot_puts("\n");
1561        boot_exit();
1562    }
1563} // end boot_get_sched_vaddr()
1564
[189]1565///////////////////////////////////////////////////////////////////////////////
1566// This function initialises all processors schedulers.
1567// This is done by processor 0, and the MMU must be activated.
[238]1568// It initialises the boot_chedulers[gpid] pointers array.
[189]1569// Finally, it scan all tasks in all vspaces to initialise the tasks contexts,
1570// as specified in the mapping_info data structure.
1571// For each task, a TTY channel, a TIMER channel, a FBDMA channel, and a NIC
[238]1572// channel are allocated if required.
[189]1573///////////////////////////////////////////////////////////////////////////////
[238]1574void boot_schedulers_init() 
1575{
1576    mapping_header_t*  header  = (mapping_header_t *) & seg_mapping_base;
1577    mapping_cluster_t* cluster = boot_get_cluster_base(header);
1578    mapping_vspace_t*  vspace  = boot_get_vspace_base(header);
1579    mapping_task_t*    task    = boot_get_task_base(header);
1580    mapping_vobj_t*    vobj    = boot_get_vobj_base(header);
1581    mapping_proc_t*    proc    = boot_get_proc_base(header);
1582    mapping_irq_t*     irq     = boot_get_irq_base(header);
[189]1583
[238]1584    unsigned int cluster_id;    // cluster index in mapping_info
1585    unsigned int proc_id;       // processor index in mapping_info
1586    unsigned int irq_id;        // irq index in mapping_info
1587    unsigned int vspace_id;     // vspace index in mapping_info
1588    unsigned int task_id;       // task index in mapping_info
1589
1590    unsigned int alloc_tty_channel = 1;            // TTY channel allocator
1591    unsigned int alloc_nic_channel = 0;            // NIC channel allocator
1592    unsigned int alloc_cma_channel = 0;            // CMA channel allocator
1593    unsigned int alloc_ioc_channel = 0;            // IOC channel allocator
[228]1594    unsigned int alloc_dma_channel[NB_CLUSTERS];   // DMA channel allocators
[238]1595    unsigned int alloc_tim_channel[NB_CLUSTERS];   // user TIMER allocators
[189]1596
[238]1597    /////////////////////////////////////////////////////////////////////////
1598    // Step 1 : loop on the clusters and on the processors
1599    //          to initialize the schedulers[] array of pointers and
1600    //          the interrupt vectors.
1601    // Implementation note:
1602    // We need to use both proc_id to scan the mapping info structure,
1603    // and lpid to access the schedulers array.
1604    // - the boot_schedulers[] array of pointers can contain "holes", because
1605    //   it is indexed by the global pid = cluster_id*NB_PROCS_MAX + ltid
1606    // - the mapping info array of processors is contiguous, it is indexed
1607    //   by proc_id, and use an offset specific in each cluster.
[189]1608
[238]1609    for (cluster_id = 0; cluster_id < header->clusters; cluster_id++) 
1610    {
[189]1611
[238]1612#if BOOT_DEBUG_SCHED
[255]1613        boot_puts("\n[BOOT DEBUG] Initialise schedulers in cluster ");
1614        boot_putd(cluster_id);
1615        boot_puts("\n");
[238]1616#endif
[189]1617
[238]1618        // TTY, NIC, CMA, IOC, TIM and DMA channels allocators
1619        // - TTY[0] is reserved for the kernel
1620        // - In all clusters the first NB_PROCS_MAX timers
1621        //   are reserved for the kernel (context switch)
1622
[228]1623        alloc_dma_channel[cluster_id] = 0;
[238]1624        alloc_tim_channel[cluster_id] = NB_PROCS_MAX;
[228]1625
[238]1626        unsigned int  lpid;          // processor local index in cluster
1627        unsigned int  sched_vbase;   // schedulers segment virtual base address
1628        unsigned int  sched_length;  // schedulers segment length
1629        unsigned int  nprocs;        // number of processors in cluster
[189]1630
[238]1631        nprocs = cluster[cluster_id].procs;
[189]1632
[238]1633        // checking processors number
1634        if ( nprocs > NB_PROCS_MAX )
1635        {
1636            boot_puts("\n[BOOT ERROR] Too much processors in cluster ");
1637            boot_putd(cluster_id);
1638            boot_puts("\n");
1639            boot_exit();
[189]1640        }
[238]1641 
1642        // get scheduler array virtual base address for cluster_id
1643        boot_get_sched_vaddr( cluster_id, &sched_vbase, &sched_length );
[189]1644
[240]1645        // each processor scheduler requires 4 Kbytes
1646        if ( sched_length < (nprocs<<12) ) 
[238]1647        {
1648            boot_puts("\n[BOOT ERROR] Schedulers segment too small in cluster ");
[228]1649            boot_putd(cluster_id);
[189]1650            boot_puts("\n");
1651            boot_exit();
1652        }
1653
[238]1654        for ( proc_id = cluster[cluster_id].proc_offset, lpid = 0 ;
1655              proc_id < cluster[cluster_id].proc_offset + cluster[cluster_id].procs;
1656              proc_id++, lpid++ ) 
1657        {
1658            // set the schedulers pointers array
1659            boot_schedulers[cluster_id * NB_PROCS_MAX + lpid] =
[240]1660               (static_scheduler_t*)( sched_vbase + (lpid<<12) );
[189]1661
1662#if BOOT_DEBUG_SCHED
[255]1663            boot_puts("\nProc ");
1664            boot_putd(lpid);
1665            boot_puts(" : scheduler virtual base address = ");
1666            boot_putx( sched_vbase + (lpid<<12) );
1667            boot_puts("\n");
[189]1668#endif
[238]1669            // current processor scheduler pointer : psched
[240]1670            static_scheduler_t* psched = (static_scheduler_t*)(sched_vbase+(lpid<<12));
[228]1671
[238]1672            // initialise the "tasks" variable
1673            psched->tasks = 0;
1674
[189]1675            // initialise the interrupt_vector with ISR_DEFAULT
1676            unsigned int slot;
[238]1677            for (slot = 0; slot < 32; slot++) psched->interrupt_vector[slot] = 0;
[189]1678
1679            // scan the IRQs actually allocated to current processor
[228]1680            for (irq_id = proc[proc_id].irq_offset;
[238]1681                 irq_id < proc[proc_id].irq_offset + proc[proc_id].irqs;
1682                 irq_id++) 
1683            {
[228]1684                unsigned int type = irq[irq_id].type;
1685                unsigned int icu_id = irq[irq_id].icuid;
1686                unsigned int isr_id = irq[irq_id].isr;
[189]1687                unsigned int channel = irq[irq_id].channel;
[228]1688                unsigned int value = isr_id | (type << 8) | (channel << 16);
[238]1689                psched->interrupt_vector[icu_id] = value;
[189]1690
1691#if BOOT_DEBUG_SCHED
[255]1692                boot_puts("- IRQ : icu = ");
1693                boot_putd(icu_id);
1694                boot_puts(" / type = ");
1695                boot_putd(type);
1696                boot_puts(" / isr = ");
1697                boot_putd(isr_id);
1698                boot_puts(" / channel = ");
1699                boot_putd(channel);
1700                boot_puts(" => vector_entry = ");
1701                boot_putx( value );
1702                boot_puts("\n");
[189]1703#endif
1704            }
1705        } // end for procs
1706    } // end for clusters
1707
[238]1708    ///////////////////////////////////////////////////////////////////
[189]1709    // Step 2 : loop on the vspaces and the tasks
1710    //          to initialise the schedulers and the task contexts.
[238]1711    // Implementation note:
1712    // This function initialises the task context for all tasks.
1713    // For each processor, the scheduler virtual base address
1714    // is written in the CP0_SCHED register in reset.S
[189]1715
[238]1716    for (vspace_id = 0; vspace_id < header->vspaces; vspace_id++) 
1717    {
[189]1718
1719#if BOOT_DEBUG_SCHED
[255]1720        boot_puts("\n[BOOT DEBUG] Initialise task contexts for vspace ");
1721        boot_puts(vspace[vspace_id].name);
1722        boot_puts("\n");
[189]1723#endif
1724        // We must set the PTPR depending on the vspace, because the start_vector
1725        // and the stack address are defined in virtual space.
[238]1726        boot_set_mmu_ptpr( (unsigned int)(boot_ptabs_paddr[vspace_id] >> 13) );
[189]1727
[197]1728        // loop on the tasks in vspace (task_id is the global index)
[228]1729        for (task_id = vspace[vspace_id].task_offset;
[238]1730             task_id < (vspace[vspace_id].task_offset + vspace[vspace_id].tasks);
1731             task_id++) 
1732        {
1733            // compute gpid (global processor index) and scheduler base address
1734            unsigned int gpid = task[task_id].clusterid * NB_PROCS_MAX + 
1735                                task[task_id].proclocid;
1736            static_scheduler_t* psched = boot_schedulers[gpid];
1737
[199]1738            // ctx_ra :  the return address is &boot_eret()
[228]1739            unsigned int ctx_ra = (unsigned int) &boot_eret;
[189]1740
[199]1741            // ctx_sr : value required before an eret instruction
[228]1742            unsigned int ctx_sr = 0x0000FF13;
[189]1743
[199]1744            // ctx_ptpr : page table physical base address (shifted by 13 bit)
[238]1745            unsigned int ctx_ptpr = (unsigned int)(boot_ptabs_paddr[vspace_id] >> 13);
[189]1746
[199]1747            // ctx_ptab : page_table virtual base address
[238]1748            unsigned int ctx_ptab = boot_ptabs_vaddr[vspace_id];
[189]1749
[238]1750            // ctx_tty : terminal global index provided by the global allocator
[199]1751            unsigned int ctx_tty = 0xFFFFFFFF;
[238]1752            if (task[task_id].use_tty) 
1753            {
1754                if (alloc_tty_channel >= NB_TTY_CHANNELS) 
1755                {
[189]1756                    boot_puts("\n[BOOT ERROR] TTY index too large for task ");
[228]1757                    boot_puts(task[task_id].name);
[189]1758                    boot_puts(" in vspace ");
[228]1759                    boot_puts(vspace[vspace_id].name);
[189]1760                    boot_puts("\n");
1761                    boot_exit();
1762                }
[199]1763                ctx_tty = alloc_tty_channel;
[189]1764                alloc_tty_channel++;
1765            }
[238]1766            // ctx_nic : NIC channel global index provided by the global allocator
[199]1767            unsigned int ctx_nic = 0xFFFFFFFF;
[238]1768            if (task[task_id].use_nic) 
1769            {
1770                if (alloc_nic_channel >= NB_NIC_CHANNELS) 
1771                {
[189]1772                    boot_puts("\n[BOOT ERROR] NIC channel index too large for task ");
[228]1773                    boot_puts(task[task_id].name);
[189]1774                    boot_puts(" in vspace ");
[228]1775                    boot_puts(vspace[vspace_id].name);
[189]1776                    boot_puts("\n");
1777                    boot_exit();
1778                }
[199]1779                ctx_nic = alloc_nic_channel;
[189]1780                alloc_nic_channel++;
1781            }
[238]1782            // ctx_cma : CMA channel global index provided by the global allocator
1783            unsigned int ctx_cma = 0xFFFFFFFF;
1784            if (task[task_id].use_cma) 
1785            {
1786                if (alloc_cma_channel >= NB_CMA_CHANNELS) 
1787                {
1788                    boot_puts("\n[BOOT ERROR] CMA channel index too large for task ");
1789                    boot_puts(task[task_id].name);
1790                    boot_puts(" in vspace ");
1791                    boot_puts(vspace[vspace_id].name);
1792                    boot_puts("\n");
1793                    boot_exit();
1794                }
1795                ctx_cma = alloc_cma_channel;
1796                alloc_cma_channel++;
1797            }
1798            // ctx_ioc : IOC channel global index provided by the global allocator
1799            unsigned int ctx_ioc = 0xFFFFFFFF;
1800            if (task[task_id].use_ioc) 
1801            {
1802                if (alloc_ioc_channel >= NB_IOC_CHANNELS) 
1803                {
1804                    boot_puts("\n[BOOT ERROR] IOC channel index too large for task ");
1805                    boot_puts(task[task_id].name);
1806                    boot_puts(" in vspace ");
1807                    boot_puts(vspace[vspace_id].name);
1808                    boot_puts("\n");
1809                    boot_exit();
1810                }
1811                ctx_ioc = alloc_ioc_channel;
1812                alloc_ioc_channel++;
1813            }
1814            // ctx_tim : TIMER local channel index provided by the cluster allocator
1815            unsigned int ctx_tim = 0xFFFFFFFF;
1816            if (task[task_id].use_tim) 
1817            {
[189]1818                unsigned int cluster_id = task[task_id].clusterid;
[215]1819
[238]1820                if ( alloc_tim_channel[cluster_id] >= NB_TIM_CHANNELS ) 
1821                {
[189]1822                    boot_puts("\n[BOOT ERROR] local TIMER index too large for task ");
[228]1823                    boot_puts(task[task_id].name);
[189]1824                    boot_puts(" in vspace ");
[228]1825                    boot_puts(vspace[vspace_id].name);
[189]1826                    boot_puts("\n");
1827                    boot_exit();
1828                }
[238]1829
1830                // checking that there is a well defined ISR_TIMER installed
1831                unsigned int found = 0;
1832                for ( irq_id = 0 ; irq_id < 32 ; irq_id++ ) 
1833                {
1834                    unsigned int entry   = psched->interrupt_vector[irq_id];
1835                    unsigned int isr     = entry & 0x000000FF;
1836                    unsigned int channel = entry>>16;
1837                    if ( (isr == ISR_TIMER) && (channel == alloc_tim_channel[cluster_id]) ) 
1838                    {
1839                        found     = 1;
1840                        ctx_tim =  alloc_tim_channel[cluster_id];
1841                        alloc_tim_channel[cluster_id]++;
1842                        break;
[215]1843                    }
1844                }
[238]1845                if (!found) 
1846                {
1847                    boot_puts("\n[BOOT ERROR] No ISR_TIMER installed for task ");
[228]1848                    boot_puts(task[task_id].name);
[215]1849                    boot_puts(" in vspace ");
[228]1850                    boot_puts(vspace[vspace_id].name);
[215]1851                    boot_puts("\n");
1852                    boot_exit();
1853                }
[189]1854            }
[238]1855            // ctx_dma : the local channel index is defined by the cluster allocator 
1856            //           but the ctx_dma value is a global index
[218]1857            unsigned int ctx_dma = 0xFFFFFFFF;
[238]1858            if ( task[task_id].use_dma ) 
1859            {
[189]1860                unsigned int cluster_id = task[task_id].clusterid;
[238]1861
1862                if (alloc_dma_channel[cluster_id] >= NB_DMA_CHANNELS) 
1863                {
[218]1864                    boot_puts("\n[BOOT ERROR] local DMA index too large for task ");
[228]1865                    boot_puts(task[task_id].name);
[189]1866                    boot_puts(" in vspace ");
[228]1867                    boot_puts(vspace[vspace_id].name);
[189]1868                    boot_puts("\n");
1869                    boot_exit();
1870                }
[238]1871                ctx_dma = cluster_id * NB_DMA_CHANNELS + alloc_dma_channel[cluster_id];
[218]1872                alloc_dma_channel[cluster_id]++;
[189]1873            }
[199]1874            // ctx_epc : Get the virtual address of the start function
[238]1875            mapping_vobj_t* pvobj = &vobj[vspace[vspace_id].vobj_offset + 
1876                                     vspace[vspace_id].start_offset];
1877            unsigned int* start_vector_vbase = (unsigned int *) pvobj->vaddr;
[199]1878            unsigned int ctx_epc = start_vector_vbase[task[task_id].startid];
[189]1879
[199]1880            // ctx_sp :  Get the vobj containing the stack
[232]1881            unsigned int vobj_id = task[task_id].stack_vobjid + vspace[vspace_id].vobj_offset;
[199]1882            unsigned int ctx_sp = vobj[vobj_id].vaddr + vobj[vobj_id].length;
[189]1883
[238]1884            // get local task index in scheduler
1885            unsigned int ltid = psched->tasks;
[189]1886
[238]1887            if (ltid >= IDLE_TASK_INDEX) 
1888            {
[197]1889                boot_puts("\n[BOOT ERROR] : ");
[228]1890                boot_putd(ltid);
[197]1891                boot_puts(" tasks allocated to processor ");
[228]1892                boot_putd(gpid);
[197]1893                boot_puts(" / max is 15\n");
[189]1894                boot_exit();
1895            }
[238]1896            // update the "tasks" field in scheduler
1897            psched->tasks = ltid + 1;
[189]1898
[238]1899            // update the "current" field in scheduler
1900            psched->current = 0;
[189]1901
[238]1902            // initializes the task context in scheduler
1903            psched->context[ltid][CTX_SR_ID]    = ctx_sr;
1904            psched->context[ltid][CTX_SP_ID]    = ctx_sp;
1905            psched->context[ltid][CTX_RA_ID]    = ctx_ra;
1906            psched->context[ltid][CTX_EPC_ID]   = ctx_epc;
1907            psched->context[ltid][CTX_PTPR_ID]  = ctx_ptpr;
1908            psched->context[ltid][CTX_TTY_ID]   = ctx_tty;
1909            psched->context[ltid][CTX_CMA_ID]   = ctx_cma;
1910            psched->context[ltid][CTX_IOC_ID]   = ctx_ioc;
1911            psched->context[ltid][CTX_NIC_ID]   = ctx_nic;
1912            psched->context[ltid][CTX_TIM_ID]   = ctx_tim;
1913            psched->context[ltid][CTX_DMA_ID]   = ctx_dma;
1914            psched->context[ltid][CTX_PTAB_ID]  = ctx_ptab;
1915            psched->context[ltid][CTX_LTID_ID]  = ltid;
1916            psched->context[ltid][CTX_GTID_ID]  = task_id;
1917            psched->context[ltid][CTX_VSID_ID]  = vspace_id;
1918            psched->context[ltid][CTX_RUN_ID]   = 1;
[228]1919
[189]1920#if BOOT_DEBUG_SCHED
[255]1921            boot_puts("\nTask ");
1922            boot_puts(task[task_id].name);
1923            boot_puts(" (");
1924            boot_putd(task_id);
1925            boot_puts(") allocated to processor ");
1926            boot_putd(gpid);
1927            boot_puts("\n  - ctx[LTID]   = ");
1928            boot_putd(ltid);
1929            boot_puts("\n  - ctx[SR]     = ");
1930            boot_putx(ctx_sr);
1931            boot_puts("\n  - ctx[SR]     = ");
1932            boot_putx(ctx_sp);
1933            boot_puts("\n  - ctx[RA]     = ");
1934            boot_putx(ctx_ra);
1935            boot_puts("\n  - ctx[EPC]    = ");
1936            boot_putx(ctx_epc);
1937            boot_puts("\n  - ctx[PTPR]   = ");
1938            boot_putx(ctx_ptpr);
1939            boot_puts("\n  - ctx[TTY]    = ");
1940            boot_putd(ctx_tty);
1941            boot_puts("\n  - ctx[NIC]    = ");
1942            boot_putd(ctx_nic);
1943            boot_puts("\n  - ctx[CMA]    = ");
1944            boot_putd(ctx_cma);
1945            boot_puts("\n  - ctx[IOC]    = ");
1946            boot_putd(ctx_ioc);
1947            boot_puts("\n  - ctx[TIM]    = ");
1948            boot_putd(ctx_tim);
1949            boot_puts("\n  - ctx[DMA]    = ");
1950            boot_putd(ctx_dma);
1951            boot_puts("\n  - ctx[PTAB]   = ");
1952            boot_putx(ctx_ptab);
1953            boot_puts("\n  - ctx[GTID]   = ");
1954            boot_putd(task_id);
1955            boot_puts("\n  - ctx[VSID]   = ");
1956            boot_putd(vspace_id);
1957            boot_puts("\n");
[189]1958#endif
1959
1960        } // end loop on tasks
1961    } // end loop on vspaces
[253]1962
1963    boot_puts("\n[BOOT] Schedulers initialisation completed at cycle ");
1964    boot_putd(boot_proctime());
1965    boot_puts("\n");
1966
[189]1967} // end boot_schedulers_init()
1968
[228]1969
[189]1970//////////////////////////////////////////////////////////////////////////////////
1971// This function is executed by P[0] to wakeup all processors.
1972//////////////////////////////////////////////////////////////////////////////////
[238]1973void boot_start_all_procs() 
1974{
[228]1975    mapping_header_t * header = (mapping_header_t *) &seg_mapping_base;
[189]1976    header->signature = OUT_MAPPING_SIGNATURE;
1977}
1978
[228]1979
[189]1980/////////////////////////////////////////////////////////////////////
1981// This function is the entry point of the initialisation procedure
1982/////////////////////////////////////////////////////////////////////
[228]1983void boot_init() {
[236]1984
[189]1985    // mapping_info checking
1986    boot_check_mapping();
1987
[200]1988    // page table building
1989    boot_pt_init();
[189]1990
[255]1991    // mmu activation (with page table [0])
[246]1992    boot_set_mmu_ptpr((unsigned int) (boot_ptabs_paddr[0] >> 13));
[238]1993    boot_set_mmu_mode(0xF);
1994
1995    boot_puts("\n[BOOT] Proc 0 MMU activation at cycle ");
1996    boot_putd(boot_proctime());
1997    boot_puts("\n");
1998
[200]1999    // vobjs initialisation
2000    boot_vobjs_init();
[189]2001
[255]2002    // reset ptpr with page table 0
2003    boot_set_mmu_ptpr((unsigned int) (boot_ptabs_paddr[0] >> 13));
2004
[200]2005    // peripherals initialisation
2006    boot_peripherals_init();
2007
[189]2008    // schedulers initialisation
2009    boot_schedulers_init();
2010
2011    // start all processors
2012    boot_start_all_procs();
2013
2014} // end boot_init()
2015
[228]2016
[189]2017// Local Variables:
2018// tab-width: 4
2019// c-basic-offset: 4
2020// c-file-offsets:((innamespace . 0)(inline-open . 0))
2021// indent-tabs-mode: nil
2022// End:
[228]2023// vim: filetype=c:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
[189]2024
Note: See TracBrowser for help on using the repository browser.