132 | | The kernel_init( boot_info_t * info ) function is the kernel entry point when the boot_loader transfer control to the kernel. The argument is a pointer on the fixed size boot_info_t structure, that is stored in the data kernel segment. |
133 | | |
134 | | All cores execute this procedure in parallel, but some tasks are only executed by the CP0 core. |
135 | | This procedure uses two synchronisation barriers, defined as global variables in the data segment: |
136 | | * the global_barrier variable is used to synchronize all CP0 cores in all clusters containing a kernel instance. |
| 132 | The kernel_init( boot_info_t * info ) function is the kernel entry point when the boot_loader transfers control to the kernel. The argument is a pointer on the fixed size boot_info_t structure, stored in the local ''kdata'' segment. |
| 133 | |
| 134 | When a core enters this function, the MMU status depends on the target architecture: |
| 135 | * For the '''TSAR''' architectures, the instruction MMU has been activated and uses the Page Table defined by the boot-loader. The data MMU is de-activated, and the DATA address extension register points on the local physical memory. |
| 136 | * For the '''I86''' architectures, both the instruction and the data MMUs have been activated, an use the Page Table defined by the boot-loader. |
| 137 | |
| 138 | In both cases, a new GPT (Generic Page Table), and a new VSL (Virtual Segments List) must be created in each cluster. These structures will be used by all kernel threads (all threads directly attached to the local kernel process) and are stored in the process_zero VMM. The ''kcode'' and (possibly) ''kdata'' segments are copied in all user process descriptors. |
| 139 | |
| 140 | In each cluster, all local cores execute this procedure in parallel, but most tasks are only executed by core[0]. |
| 141 | This procedure uses two synchronisation barriers, defined as global variables in the ''kdata'' segment: |
| 142 | * the global_barrier variable is used to synchronize all core[0] in all clusters containing a kernel instance. |
144 | | From the kernel point of view a core is identified by a composite index (cxy,lid), where '''cxy''' is the cluster identifier, and ''lid'' is a local (continuous) index in the cluster. The association between the gid hardware index and the (cxy,lid) composite index is defined in the boot_info_t structure. |
145 | | In this first step, each core makes an associative search in the boot_info_t structure to obtain the ('''cxy,lid''') indexes from the '''gid''' index. |
146 | | Then the CP0 initialize the global variable '''local_cxy''' defining the local cluster identifier. |
147 | | |
148 | | === D2) TXT0 device initialization === |
149 | | |
150 | | The core[io_cxy][0] (i.e. CP0 in I/O cluster) initializes the chdev descriptor associated to the kernel text terminal TXT0. This terminal is used by any kernel instance running on any core to display log or debug messages. This terminal is configured in ''non-descheduling'' mode : |
151 | | the calling thread call directly the relevant TXT driver, without using a server thread. |
152 | | |
153 | | A first synchonization barrier is used to avoid other cores to use the TXT0 terminal before initialization completion. |
154 | | |
155 | | === D3) Cluster manager initialization === |
156 | | |
157 | | In each cluster, the CP0 makes the cluster manager initialization, namely the cores descriptors array, and the physical memory allocators. |
158 | | Then it initializes the local process_zero, containing al kernel threads in a given cluster. |
159 | | |
160 | | A second synchonization barrier is used to avoid other cores to access cluster manager before initialization completion. |
161 | | |
162 | | === D4) Internal & external devices initialization === |
163 | | |
164 | | In each cluster, the CP0 makes the devices initialization. For multi-channels devices, there is one channel device (called chdev_t) per channel. |
165 | | For internal (replicated) devices, the khedive descriptors are allocated in the local cluster. For external (shared) devices, the chdev descriptors are regularly distributed on all clusters. These external chdev are indexed by a global index, and the host cluster is computed from this |
166 | | index by a modulo. |
| 150 | From the kernel point of view a core is identified by a composite index (cxy,lid), where '''cxy''' is the cluster identifier, and ''lid'' is a local (continuous) index in the cluster. The association between the gid hardware index and the (cxy,lid) composite index is defined in the boot_info_t structure. In this first step, each core makes an associative search in the boot_info_t structure to obtain the ('''cxy,lid''') indexes from the '''gid''' index. |
| 151 | |
| 152 | The core[0] initialize the global variable '''local_cxy''' defining the local cluster identifier, and initialises the local cluster descriptor from informations found in the boot_info_t structure. |
| 153 | All cores makes a first initialization of their private kernel ''idle_thread''. |
| 154 | Finally, the core[0] in cluster[0] initialise the kernel TXT0. This terminal is used by any kernel instance running on any core to display log or debug messages. This terminal is configured in ''non-descheduling'' mode : the calling thread call directly the relevant TXT driver, without using a server thread. |
| 155 | |
| 156 | A synchronization barrier is used to avoid other cores to use the TXT0 terminal before initialization. |
| 157 | |
| 158 | === D2) Cluster manager initialization === |
| 159 | |
| 160 | In each cluster, the core[0] makes the cluster manager initialization, namely the cores descriptors array, the DQDT, and the local physical memory allocators. |
| 161 | |
| 162 | A synchonization barrier is used to avoid access to cluster manager before initialization. |
| 163 | |
| 164 | === D3) Process_zero initialization === |
| 165 | |
| 166 | In each cluster the core[0] initializes the local process_zero descriptor, containing al kernel threads in a given cluster. |
| 167 | This include the creation of the local kernel GPT and VSL. |
| 168 | |
| 169 | A synchronization barrier is used to avoid access to VSL/GPT before initialization. |
| 170 | |
| 171 | === D4) MMU activation === |
| 172 | |
| 173 | In each cluster, all cores activate their private MMU, as required by the architecture. |
| 174 | For TSAR, only the instruction MMU is activated, but the data MMU is de-activated. |
| 175 | |
| 176 | Moreover, the core[0] in cluster[0] initializes the external IOPIC device |
| 177 | |
| 178 | A synchronization barrier is used to avoid access to IOPIC before initialization. |
| 179 | |
| 180 | === D5) Internal & external devices initialization === |
| 181 | |
| 182 | In each cluster, the core[0] makes the devices initialization. For multi-channels devices, there is one channel device (called chdev_t) per channel. |
| 183 | For internal (replicated) devices, the chdev descriptors are allocated in the local cluster. For external (shared) devices, the chdev descriptors are regularly distributed on all clusters. These external chdev are indexed by a global index, and the host cluster is computed from this index by a modulo. |
170 | | Then each external chdev descriptor is created by the CP0 in the cluster where it must be created. |
171 | | |
172 | | A third synchonization barrier is used to avoid other cores to access devices before initialization completion. |
173 | | |
174 | | === D5) Idle thread initialization === |
175 | | |
176 | | In this step, each core creates and initializes its private idle thread descriptor. |
177 | | |
178 | | === D6) File system initialization === |
179 | | |
180 | | The CP0 in I/O cluster) initializes the file system. |
181 | | |
182 | | A fourth synchonization barrier is used to avoid other cores to access file system before initialization completion. |
183 | | |
184 | | === D7) Scheduler activation === |
185 | | |
186 | | Finally, each core enables its private timer IRQ to activate its private scheduler, and jump to the idle thread code.= Boot procedure = |
| 187 | Then each external chdev descriptor is created in the cluster where it must be created. |
| 188 | |
| 189 | A synchronization barrier is used to avoid access to devices before initialization. |
| 190 | |
| 191 | === D6) IPI, Idle thread, and VFS root initialization === |
| 192 | |
| 193 | Each core enable its private input IPI, and completes initialization of its private idle thread descriptor. |
| 194 | |
| 195 | Then core[0] in cluster[0] creates the root VFS in cluster[0]. This requires to access the file system on disk. |
| 196 | |
| 197 | A synchronization barrier is used to avoid access to VFS root before initialization. |
| 198 | |
| 199 | === D7) VFS root initialisation in all clusters === |
| 200 | |
| 201 | In each cluster other than cluster[0], the core[0] initializes the VFS and FS contexts in the local cluster, |
| 202 | from values registered in cluster[0]. |
| 203 | |
| 204 | A synchronization barrier is used to avoid access to VFS before initialization. |
| 205 | |
| 206 | === D8) DEVFS global initialization === |
| 207 | |
| 208 | The core[0] in cluster[0] makes the DEVFS global initialization: It initializes the DEVFS context, and creates the DEVFSb''dev'' and ''external'' directory inodes in cluster[0]. |
| 209 | |
| 210 | A synchronization barrier is used to avoid access to DEVFS root before initialization. |
| 211 | |
| 212 | === D9) DEVFS local initialization === |
| 213 | |
| 214 | In each cluster[cxy], the core[0] completes in parallel the DEVFS initialization. Each core[0] get the extended pointers on the ''dev'' and ''external'' directories from values stored in cluster[0]. Then each core[0] creates the DEVFS ''internal'' directory, and creates the pseudo-files for all chdevs in cluster[cxy]. |
| 215 | |
| 216 | A synchronization barrier is used to avoid access to DEVFS before initialization. |
| 217 | |
| 218 | === D10) Process init creation === |
| 219 | |
| 220 | The core[0] in cluster[0] creates (i.e. allocates memory, and initializes) the process descriptor for the first user process. This includes the VMM initialization (both the user GPT and VSL inherits relevant informations from the kernel GPT and VSL). |
| 221 | |
| 222 | The core[0] in cluster[0] displays the ALMOS-MK banner. |
| 223 | |
| 224 | A last synchronization barrier is used before jumping to idle_thread function |
| 225 | |
| 226 | === D11) Enter idle_thread === |
| 227 | |
| 228 | Finally, each core enables its private timer IRQ to activate its private scheduler, and jump to the idle_thread code, |
| 229 | that contains an infinite loop waiting for an useful thread to be scheduled. |