forked from BSB-WS23/mpstubs
110 lines
4.0 KiB
C++
110 lines
4.0 KiB
C++
/*! \file
|
|
* \brief Startup of additional cores, the application processors (APs)
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#include "types.h"
|
|
#include "compiler/fix.h"
|
|
|
|
/*! \brief Application Processor Boot
|
|
*
|
|
* Interface to boot the APs
|
|
*/
|
|
namespace ApplicationProcessor {
|
|
/*! \brief Address (below 1 MiB) to which the setup code gets relocated
|
|
*/
|
|
const uintptr_t RELOCATED_SETUP = 0x40000;
|
|
|
|
/*! \brief Relocate the real mode setup code
|
|
*
|
|
* The application processors (APs) start in real mode, which means that your setup
|
|
* code must be placed within the first megabyte -- your operating system resides
|
|
* currently at a much higher address (16 MiB), so the code has to be copied
|
|
* down there first.
|
|
*
|
|
* Luckily, the code in `setup_ap()` can be relocated by copying -- because it
|
|
* does not use any absolute addressing (except when jumping to the protected
|
|
* mode function `startup_ap()`).
|
|
* The function must be copied to the address of \ref RELOCATED_SETUP (0x40000),
|
|
* so that the APs can start there.
|
|
*
|
|
* The memory section contains a reserved area for the \ref GDT and its descriptor,
|
|
* which has to be assigned first with the contents of \ref ap_gdt.
|
|
*
|
|
* \note You could also tell the linker script to put the code directly
|
|
* at the appropriate place, but unfortunately the Qemu multiboot
|
|
* implementation (via `-kernel` parameter) can't handle it properly.
|
|
*/
|
|
void relocateSetupCode();
|
|
|
|
/*! \brief Boot all application processors
|
|
*
|
|
* Performs relocation by calling \ref relocateSetupCode()
|
|
*
|
|
* \see [ISDMv3, 8.4.4.2 Typical AP Initialization Sequence](intel_manual_vol3.pdf#page=276)
|
|
*/
|
|
void boot();
|
|
} // namespace ApplicationProcessor
|
|
|
|
/*! \brief Begin of setup code for application processors
|
|
*
|
|
* The setup code has to switch from real mode (16 bit) to protected mode (32 bit),
|
|
* hence it is written in assembly and must be executed in low memory (< 1 MiB).
|
|
*
|
|
* After kernel start the code is somewhere above 16 MiB (the bootstrap
|
|
* processor was already launched in protected mode by the boot loader).
|
|
* Therefore this symbol is required for relocate the code to the position
|
|
* specified by \ref ApplicationProcessor::RELOCATED_SETUP.
|
|
*
|
|
* Luckily, the `setup_ap` code in `boot/startup_ap.asm` is rather simple and
|
|
* doesn't depend on absolute addressing -- and is therefore relocatable.
|
|
*
|
|
* Relocation is done by the function \ref ApplicationProcessor::relocateSetupCode()
|
|
*
|
|
* The `___SETUP_AP_START__` symbol is defined in the linker script (`compiler/section.ld`)
|
|
*/
|
|
extern char ___SETUP_AP_START__;
|
|
|
|
/*! \brief End of startup code for application processors
|
|
*
|
|
* This Symbol is defined in the linker script (`compiler/section.ld`)
|
|
*/
|
|
extern char ___SETUP_AP_END__;
|
|
|
|
/*! \brief Memory reserved for a temporary real mode GDT
|
|
* within the relocatable memory area of the setup code
|
|
*/
|
|
extern char setup_ap_gdt;
|
|
|
|
/*! \brief Memory reserved for a temporary real mode GDT descriptor
|
|
* within the relocatable memory area of the setup code
|
|
*/
|
|
extern char setup_ap_gdtd;
|
|
|
|
/*! \brief Entry point for application processors
|
|
*
|
|
* Unlike the bootstrap processor, the application processors have not been
|
|
* setup by the boot loader -- they start in `Real Mode` (16 bit) and have to be
|
|
* switched manually to `Protected Mode` (32 bit).
|
|
* This is exactly what this real mode function does, handing over control
|
|
* to the (32 bit) function \ref startup_ap()
|
|
*
|
|
* This code is written is assembly (`boot/startup_ap.asm`) and relocated by
|
|
* \ref ApplicationProcessor::relocateSetupCode() during
|
|
* \ref ApplicationProcessor::boot()
|
|
*/
|
|
extern "C" void setup_ap()
|
|
ERROR_ON_CALL("The setup function for application processors shall never be called from your code!");
|
|
|
|
/*! \brief Startup for application processors
|
|
* \ingroup Startup
|
|
*
|
|
* This function behaves similar to \ref startup_bsp():
|
|
* Initializes stack pointer,
|
|
* switches to long mode
|
|
* and calls the C++ \ref kernel_init function
|
|
*/
|
|
extern "C" void startup_ap()
|
|
ERROR_ON_CALL("The startup function for application processors shall never be called from your code!");
|