forked from BSB-WS23/mpstubs
113 lines
3.6 KiB
C
113 lines
3.6 KiB
C
|
/*! \file
|
||
|
* \brief Access to internals of a CPU \ref Core
|
||
|
*/
|
||
|
|
||
|
/*! \defgroup sync CPU Synchronization
|
||
|
*
|
||
|
* The synchronization module houses functions useful for orchestrating multiple processors and their activities.
|
||
|
* Synchronisation, in this case, means handling the resource contention between multiple participants, running on
|
||
|
* either the same or different cores.
|
||
|
*/
|
||
|
|
||
|
#pragma once
|
||
|
|
||
|
#include "types.h"
|
||
|
#include "machine/core_cr.h"
|
||
|
#include "machine/core_interrupt.h"
|
||
|
#include "machine/core_msr.h"
|
||
|
|
||
|
/*! \brief Implements an abstraction for CPU internals.
|
||
|
*
|
||
|
* These internals include functions to \ref Core::Interrupt "allow or deny interrupts",
|
||
|
* access \ref Core::CR "control registers".
|
||
|
*/
|
||
|
namespace Core {
|
||
|
|
||
|
/*! \brief Maximum number of supported CPUs
|
||
|
*/
|
||
|
const unsigned MAX = 8;
|
||
|
|
||
|
/*! \brief Get the ID of the current CPU core
|
||
|
* using \ref LAPIC::getID() with an internal lookup table.
|
||
|
*
|
||
|
* \return ID of current Core (a number between 0 and \ref Core::MAX)
|
||
|
*/
|
||
|
unsigned getID();
|
||
|
|
||
|
/*! \brief Initialize this CPU core
|
||
|
*
|
||
|
* Mark this core as *online* and setup the cores \ref LAPIC by assigning it a
|
||
|
* unique \ref APIC::getLogicalAPICID() "logical APIC ID"
|
||
|
*
|
||
|
* \note Should only be called from \ref kernel_init() during startup.
|
||
|
*/
|
||
|
void init();
|
||
|
|
||
|
/*! \brief Deinitialize this CPU core
|
||
|
*
|
||
|
* Mark this Core as *offline*
|
||
|
*
|
||
|
* \note Should only be called from \ref kernel_init() after returning from `main()` or `main_ap()`.
|
||
|
*/
|
||
|
void exit();
|
||
|
|
||
|
/*! \brief Get number of available CPU cores
|
||
|
*
|
||
|
* \return total number of cores
|
||
|
*/
|
||
|
unsigned count();
|
||
|
|
||
|
/*! \brief Get number of successfully started (and currently active) CPU cores
|
||
|
*
|
||
|
* \return total number of online cores
|
||
|
*/
|
||
|
unsigned countOnline();
|
||
|
|
||
|
/*! \brief Check if CPU core is currently active
|
||
|
* \param core_id ID of the CPU core
|
||
|
* \return `true` if successfully started and is currently active
|
||
|
*/
|
||
|
bool isOnline(uint8_t core_id);
|
||
|
|
||
|
/*! \brief Gives the core a hint that it is executing a spinloop and should sleep "shortly"
|
||
|
*
|
||
|
* Improves the over-all performance when executing a spinloop by waiting a short moment reduce
|
||
|
* the load on the memory.
|
||
|
*
|
||
|
* \see [ISDMv2, Chapter 4. PAUSE - Spin Loop Hint](intel_manual_vol2.pdf#page=887)
|
||
|
*/
|
||
|
inline void pause() {
|
||
|
asm volatile("pause\n\t" : : : "memory");
|
||
|
}
|
||
|
|
||
|
/*! \brief Halt the CPU core until the next interrupt.
|
||
|
*
|
||
|
* Halts the current CPU core such that it will wake up on the next interrupt. Internally, this function first enables
|
||
|
* the interrupts via `sti` and then halts the core using `hlt`. Halted cores can only be woken by interrupts.
|
||
|
* The effect of `sti` is delayed by one instruction, making the sequence `sti hlt` atomic (if interrupts were
|
||
|
* disabled previously).
|
||
|
*
|
||
|
* \see [ISDMv2, Chapter 4. STI - Set Interrupt Flag](intel_manual_vol2.pdf#page=1297)
|
||
|
* \see [ISDMv2, Chapter 3. HLT - Halt](intel_manual_vol2.pdf#page=539)
|
||
|
*/
|
||
|
inline void idle() {
|
||
|
asm volatile("sti\n\t hlt\n\t" : : : "memory");
|
||
|
}
|
||
|
|
||
|
/*! \brief Permanently halts the core.
|
||
|
*
|
||
|
* Permanently halts the current CPU core. Internally, this function first disables the interrupts via `cli` and
|
||
|
* then halts the CPU core using `hlt`. As halted CPU cores can only be woken by interrupts, it is guaranteed that
|
||
|
* this core will be halted until the next reboot. The execution of die never returns.
|
||
|
* On multicore systems, only the executing CPU core will be halted permanently, other cores will continue execution.
|
||
|
*
|
||
|
* \see [ISDMv2, Chapter 3. CLI - Clear Interrupt Flag](intel_manual_vol2.pdf#page=245)
|
||
|
* \see [ISDMv2, Chapter 3. HLT - Halt](intel_manual_vol2.pdf#page=539)
|
||
|
*/
|
||
|
[[noreturn]] inline void die() {
|
||
|
while (true) {
|
||
|
asm volatile("cli\n\t hlt\n\t" : : : "memory");
|
||
|
}
|
||
|
}
|
||
|
} // namespace Core
|