paulbergmann_mpstubs/machine/core.h

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