The objective of this project is fix and complete SMP support (multiprocessing) in GNU/Hurd
GNU/Hurd includes a tiny SMP support, as this FAQ explain
But this support is very limited:
-
GNU Mach don't detect CPUs in runtime: The number of CPUs must be hardcoded in compillation time
-
The special cases to multicore in gnumach source code haven't been never tested, so these can contain many errors. Furthermore, these special case are incomplete: many funcions, as
cpu_number()
orintel_startCPU()
aren't written. -
GNU Mach doesn't initialize the processor with the properly options to multiprocessing. By this reason, the current support is only multithread, not real multiprocessor
Added to this, there are other problem: Many drivers included in Hurd aren't thread-safe, and these could crash in a SMP environment. So, It's necessary to isolate this drivers, to avoid concurrency problems
To solve this, we need to implement some routines to detect the number of processors, assign an identifier to each processor, and configure the lapic and IPI support. This routines must been executed during Mach boot.
"Really, all the support you want to get from the hardware is just getting the number of processors, initializing them, and support for interprocessor interrupts (IPI) for signalling." - Samuel Thibault
"The process scheduler probably already has the support. What is missing is the hardware driver for SMP: enumeration and initialization." - Samuel Thibault
The current necessary functions are cpu_number()
(in kern/cpu_number.h) and intel_startCPU()
.
Another not-implemented function, but don't critical, is cpu_control()
Reference
Other interesting files are pmap.c
and sched_prim.c
Added to this, we have to build an isolated enviroment to execute the non-thread-safe drivers.
"Yes, this is a real concern. For the Linux drivers, the long-term goal is to move them to userland anyway. For Mach drivers, quite often they are not performance-sensitive, so big locks would be enough." - Samuel Thibault
-
Implement a routine to detect and identify the processors: This routine must check the number of processors, initialize the lapic of BSP, and assign a kernel ID for each processor. This kernel ID don't have to be equal to the APIC ID.
The relation Kernel/APIC can be setted with an array, where the kernel ID is the index, and the APIC data the contains.
The APIC ID can be get from memory, once lapic is initialized.The task to do in this routine are:
- Detect the number of processors
- Creates a array indexed by kernel ID, which set a relation with APIC ID.
- Initialize the lapic of BSP
- Initialize IOAPIC
This routine could be called from
i386at_init()
(i386/i386at/model_dep.c). This function will call to the functions which initialize the lapic and the ioapic.We can find a function example in XV6: XV6 reference
NOTE: This routine must be execute in first time, previously to
intel_startCPU()
or other routines.1.1. Implements
cpu_number()
function: this function must return the kernel ID of the processor which is executing the function. To do this, the function search in the Kernel/APIC array until find the APIC of the current processor. Once this APIC is find, the function will return the index (Kernel ID) of this position. - Detect the number of processors
-
Implements
intel_startCPU()
: This function will launch the startup IPI in each processor. This function will be execute during the boot of the kernel (process 0).This function also configures the support to InterProcess Interruptions (IPI), using Startup IPI.
The task to do in this function are:
- Launch Startup IPI to each processor
We have a current implementation of
intel_startCPU()
in this link. This implementation is based in XNU'sintel_startCPU()
function -
Implements another routine to start the processors, and initialize them: This routine will initialize the lapic of each processor and other structures needed to run the kernel.
(...)
We can to use XV6 source code. as reference to implements the function and routines. Some interesting files are lapic.c
, proc.c
and main.c