summaryrefslogtreecommitdiff
path: root/open_issues
diff options
context:
space:
mode:
Diffstat (limited to 'open_issues')
-rw-r--r--open_issues/smp.mdwn248
1 files changed, 1 insertions, 247 deletions
diff --git a/open_issues/smp.mdwn b/open_issues/smp.mdwn
index 9820f561..ce2c2ce2 100644
--- a/open_issues/smp.mdwn
+++ b/open_issues/smp.mdwn
@@ -56,7 +56,7 @@ Once you have the Hurd running you can build an SMP enabled GNU Mach.
$ autoreconf -i
$ mkdir build
$ cd build
- $ ../configure --enable-ncpus=4 --enable-apic --enable-kdb --disable-linux-groups
+ $ ../configure --enable-ncpus=4 --enable-kdb
$ make gnumach.gz
$ su
# mv /boot/gnumach-1.8-486.gz /boot/gnumach-1.8-486.gz.bak
@@ -88,252 +88,6 @@ To test smp:
smp.c source can be found
[[here|https://lists.gnu.org/archive/html/bug-hurd/2024-02/msg00088.html]].
-# What was done to get the 32-bit SMP support
-
-The GNU Mach source code includes many special cases for multiprocessor,
-controlled by #if NCPUS > 1 macro.
-
-But this support is very limited:
-
-- GNU Mach don't detect CPUs in runtime: The number of CPUs must be hardcoded in
-compilation time. The number of cpus is set in `mach_ncpus` configuration
-variable, set to 1 by default, in configfrag.ac file. This variable will
-generate `NCPUS` macro, which is used by gnumach to control the special cases
-for multiprocessor. If `NCPUS` > 1, then gnumach will enable multiprocessor
-support, with the number of cpus set by the user in mach_ncpus
-variable. Otherwise, SMP will be disabled.
-
-- The special cases to multicore in gnumach source code have never been tested,
- so these can contain many errors. Furthermore, these special case are
- incomplete: many functions, such as `cpu_number()` or `intel_startCPU()` aren't
- written.
-
-- GNU Mach doesn't initialize the processor with the proper options for
- multiprocessing. For this reason, the current support is only multithread and
- not real multiprocessor support.
-
-- 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.
-
-
-### Solution
-
-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. These routines must be 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 signaling." - Samuel Thibault
-> [link](https://lists.gnu.org/archive/html/bug-hurd/2018-08/msg00071.html)
-
-> "The process scheduler probably already has the support. What is missing is
-the hardware driver for SMP: enumeration and initialization." - Samuel Thibault
-[link](https://lists.gnu.org/archive/html/bug-hurd/2018-08/msg00083.html)
-
-The current necessary functions are `cpu_number()` (in kern/cpu_number.h) and
-`intel_startCPU()`. Another non-critical function, is `cpu_control()`
-[*Reference*](https://www.gnu.org/software/hurd/gnumach-doc/Processor-Control.html#Processor-Control)
-
-Other interesting files are `pmap.c` and `sched_prim.c` We also
-have to build an isolated environment 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
-> [link](https://lists.gnu.org/archive/html/bug-hurd/2018-08/msg00073.html)
-
-### Task list
-
-1. DONE Implement a routine to detect and identify the processors
-
- This routine must check the number of processors, initialize the lapic of BSP
- (the master processor), and assign a kernel ID for each processor. This kernel
- ID does not have to be equal to the APIC ID. The relation kernel/APIC can be
- settled with an array, where the kernel ID is the index, and the APIC contains
- the data. GNU Mach can derive the list of processors from memory, reading from
- ACPI table, or from MP table. However, MP table is deprecated in most modern
- CPUs, so it is preferable to use ACPI table for this.
-
- The tasks to do for this are:
-
- - Detect the number of processors
-
- - Create a array indexed by kernel ID, which sets 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 the functions which
- initialize the lapic and the ioapic.
-
- **NOTE**: This routine must be executed before `intel_startCPU()` or other routines.
-
- - **How to find APIC table**
-
- To find APIC table, we can read
- RSDT table [RSDT reference](http://www.uefi.org/sites/default/files/resources/ACPI%206_2_A_Sept29.pdf#G10.1358180).
- To get the address of RSDT, we need to read RDSP table. We can get the
- RSDP table by this [RDSP
- reference](http://www.uefi.org/sites/default/files/resources/ACPI%206_2_A_Sept29.pdf#G10.1357698)
- Once we have the RSDT table, we need to read *Entry* field, and search the pointer to
- the APIC table in the array referenced in this field.
-
- We can find an example about reading ACPI table in X15 OS:
- [Reference](https://github.com/richardbraun/x15/blob/0c0e2a02a42a8161e1b8dc1e1943fe5057ecb3a3/arch/x86/machine/acpi.c#L576)
-
- - We need to initialize the `machine_slot` of each processor (currently only initializes cpu0).
- The `machine_slot` has this structure. [Reference](https://github.com/AlmuHS/GNUMach_SMP/blob/0d490ef21c156907f3f26a6cdc00842f462a877a/include/mach/machine.h#L68):
-
- > `struct machine_slot { /*boolean_t*/` <br/>
- > `integer_t is_cpu;` <br/>
- > `/* is there a cpu in this slot? */ ` <br/>
- > `cpu_type_t cpu_type; /* type of cpu */` <br/>
- > `cpu_subtype_t cpu_subtype; /* subtype of cpu */` <br/>
- > `/*boolean_t*/ integer_t running; /* is cpu running */` <br/>
- > `integer_t cpu_ticks[CPU_STATE_MAX]; integer_t` <br/>
- > `clock_freq; /* clock interrupt frequency */ };` <br/>
-
-
- We can find an example of initialization in this [link:](https://github.com/AlmuHS/GNUMach_SMP/blob/0d490ef21c156907f3f26a6cdc00842f462a877a/i386/i386at/model_dep.c#L612)
-
- This modification also involve the redefinition of `NCPUS`, which must be set
- to the maximum **possible** number of processors. We can do this by modifying
- `configfrag.ac`, with this:
-
- > `# Multiprocessor support is still broken.` <br/>
- > `AH_TEMPLATE([MULTIPROCESSOR], [set things up for a uniprocessor])` <br/>
- > `mach_ncpus=2` <br/>
- > `AC_DEFINE_UNQUOTED([NCPUS], [$mach_ncpus], [number of CPUs])` </br>
- > `[if [$mach_ncpus` > `-gt 1 ]; then]` <br/>
- > `AC_DEFINE([MULTIPROCESSOR], [1], [set things up for a` > `multiprocessor])`
- > `AC_DEFINE_UNQUOTED([NCPUS], [256], [number of CPUs]) ` <br/>
- > `[fi]` <br/>
-
- - Interesting files and functions - `machine.c`
- [Link](https://github.com/AlmuHS/GNUMach_SMP/blob/master/kern/machine.c)
- - `c_boot_entry()`
- [Link](https://github.com/AlmuHS/GNUMach_SMP/blob/0d490ef21c156907f3f26a6cdc00842f462a877a/i386/i386at/model_dep.c#L529)
-
- - Example, in X15 OS:
- [Link](https://github.com/richardbraun/x15/blob/d6d90a3276a09da65690b019e985392bf77b53b0/arch/x86/machine/cpu.c#L1114)
-
- 1.1. Implement a `cpu_number()` function.
-
-
- This function must return the kernel ID of the processor which is executing the function. To
- get this, we have to read the local apic memory space, which will show the
- lapic of the current CPU. Reading the lapic, we can get its APIC ID. Once
- we have the APIC ID of the current CPU, the function will search in the
- Kernel/APIC array until it finds the same APIC ID. Then it will return the
- index (Kernel ID) of this position.
-
-2. DONE Implement a routine to initialize the processors
-
-
- This routine will initialize the lapic of each processor and other structures
- needed to run the kernel. We can find an example of lapic initialization
- here
- [reference](https://github.com/mit-pdos/xv6-public/blob/b818915f793cd20c5d1e24f668534a9d690f3cc8/lapic.c#L55)
- Also, we can get more information in Chapter 8.4 and 8.11 of Intel
- Developer Guide,
- Volume 3. [link](https://software.intel.com/sites/default/files/managed/a4/60/325384-sdm-vol-3abcd.pdf)
-
-3. DONE Implement `intel_startCPU()`
-
-
- This function will initialize the descriptor tables of the processor specified by the
- parameter, and launch the startup IPI to this processor. This function will be
- executed during the boot of the kernel (process 0). The task to do in this function
- are:
-
- - Initialize the processor descriptor tables
- - Launch Startup IPI to this processor
- We have a current implementation of `intel_startCPU()` in this
- [link](https://github.com/AlmuHS/GNUMach_SMP/blob/smp/i386/i386/mp_desc.c).
- This implementation is based in XNU's `intel_startCPU()`
- [function](https://github.com/nneonneo/osx-10.9-opensource/blob/f5a0b24e4d98574462c8f5e5dfcf0d37ef7e0764/xnu-2422.1.72/osfmk/i386/mp.c#L423)
-
- We can find explainations about how to raise an IPI in this pages:
- [*Reference 1*](https://www.cs.usfca.edu/~cruse/cs630f08/lesson22.ppt),
- [*Reference 2*](https://www.cheesecake.org/sac/smp.html), [*Reference
- 3*](http://www.dis.uniroma1.it/pub/quaglia/AOSV-traps-interrupts.pdf) We can
- get information about how to raise an IPI in Intel Developer Guide, Volume 3,
- Chapter 10.6
-
-4. Implement another routine to start the processors
-
-
- This routine calls to `processor_start()` for each processor, which will start the
- processor using this sequence of calls: [`processor_start(processor_t
- processor)`](https://github.com/AlmuHS/GNUMach_SMP/blob/5d527f532dfba9f2da54555d5fbe585dd458579b/kern/processor.c#L447)
- ->
- [`cpu_start(processor->slot_num)`](https://github.com/AlmuHS/GNUMach_SMP/blob/5d527f532dfba9f2da54555d5fbe585dd458579b/i386/i386/mp_desc.c#L335)
- ->
- [`intel_startCPU(cpu)`](https://github.com/AlmuHS/GNUMach_SMP/blob/5d527f532dfba9f2da54555d5fbe585dd458579b/i386/i386/mp_desc.c#L180)
-
- These articles shows some annotations about how to do the AP Startup:
-
- - [Reference1](https://wiki.osdev.org/Symmetric_Multiprocessing#AP_startup),
- - [Reference2](https://stackoverflow.com/a/16368043/7077301) (...)
-
- After implement IPI support, It's recommended reimplement `machine_idle()`,
- `machine_relax ()`, `halt_cpu()` and `halt_all_cpus()` using IPI.
- - [reference](https://github.com/AlmuHS/GNUMach_SMP/blob/0d490ef21c156907f3f26a6cdc00842f462a877a/i386/i386at/model_dep.c#L201)
- - Also in `ast_check.c`, we have to implement both functions, using
- IPI
- [Reference](https://github.com/AlmuHS/GNUMach_SMP/blob/master/i386/i386/ast_check.c)
-
-
- This functions must force the processors to check if there are any AST
- signal, and we ought to keep in the mind the following irc chat:
-
-
-> <AlmuHS> what is the use of AST in gnumach? <br/>
-> <AlmuHS> this file what do? <br/>
-> https://github.com/AlmuHS/GNUMach_SMP/blob/master/i386/i386/ast_check.c <br/>
-> <youpi> I don't know <br/>
-> <youpi> but look at what calls that <br/>
-> <youpi> see e.g. the call in thread.c <br/>
-> <AlmuHS> This <br/>
-> function is called during the sequence of cpu_up(), in machine.c <br/>
-> <AlmuHS> but only if NCPUS > 1 <br/>
-> <youpi> it seems like it's to trigger an AST check on another <br/>
-> processor <br/>
-> <youpi> i.e. a processor tells another to run ast_check <br/>
-> <youpi> (see the comment in thread.c) <br/>
-> <AlmuHS> <br/>
-> https://github.com/AlmuHS/GNUMach_SMP/blob/master/kern/machine.c <br/>
-> <youpi> well, the initialization part is not necessarily what's
-> important to <br/>
-> think about at first <br/>
-> <youpi> i.e. until you know what you'll have <br/>
-> to do during execution, you don't know what you'll need to intialize at <br/>
-> initialization <br/>
-> <youpi> you might even not need to initialize anything <br/>
-> <AlmuHS> then, this is the reason because all functions <br/>
-> in ast_check.c are empty <br/>
-> <youpi> cause_ast_check being empty is really probably a TODO <br/>
-> <AlmuHS> but I'm not clear what I need to write in this functions <br/>
-> <youpi> what the comment said: make another processor run ast_check() <br/>
-> <youpi> which probably means raising an inter-processor interrupt <br/>
-> <youpi> (aka IPI) <br/>
-> <youpi> to get ast_check() called by the other processor <br/>
-> <AlmuHS> then, this funcions must raise an IPI in the processor? <br/>
-> <youpi> that's the idea <br/>
-> <youpi> the IPI probably needs some setup <br/>
-
-We can use [XV6 source
- code](https://pdos.csail.mit.edu/6.828/2018/xv6.html). as model to implements
- the function and routines. Some interesting files are
- [`lapic.c`](https://github.com/mit-pdos/xv6-public/blob/master/lapic.c),
- [`proc.c`](https://github.com/mit-pdos/xv6-public/blob/master/proc.c) and
- [`main.c`](https://github.com/mit-pdos/xv6-public/blob/master/main.c)
-
-
## References
- [Comments about the project bug-hurd
maillist](https://lists.gnu.org/archive/html/bug-hurd/2018-08/msg00048.html)