Files
jsix/src/kernel/idt.h
Justin C. Miller 2d4a65c654 [kernel] Pre-allocate cpu_data and pass to APs
In order to avoid cyclic dependencies in the case of page faults while
bringing up an AP, pre-allocate the cpu_data structure and related CPU
control structures, and pass them to the AP startup code.

This also changes the following:
- cpu_early_init() was split out of cpu_early_init() to allow early
  usage of current_cpu() on the BSP before we're ready for the rest of
  cpu_init(). (These functions were also renamed to follow the preferred
  area_action naming style.)
- isr_handler now zeroes out the IST entry for its vector instead of
  trying to increment the IST stack pointer
- the IST stacks are allocated outside of cpu_init, to also help reduce
  stack pressue and chance of page faults before APs are ready
- share stack areas between AP idle threads so we only waste 1K per
  additional AP for the unused idle stack
2021-02-10 15:44:07 -08:00

64 lines
1.5 KiB
C++

#pragma once
/// \file idt.h
/// Definitions relating to a CPU's IDT table
#include <stdint.h>
class IDT
{
public:
IDT();
/// Install this IDT to the current CPU
void install() const;
/// Add the IST entries listed in the ISR table into the IDT.
/// This can't be done until after memory is set up so the
/// stacks can be created.
void add_ist_entries();
/// Get the IST entry used by an entry.
/// \arg i Which IDT entry to look in
/// \returns The IST index used by entry i, or 0 for none
inline uint8_t get_ist(uint8_t i) const {
return m_entries[i].ist;
}
/// Set the IST entry used by an entry.
/// \arg i Which IDT entry to set
/// \arg ist The IST index for entry i, or 0 for none
void set_ist(uint8_t i, uint8_t ist) { m_entries[i].ist = ist; }
/// Get the IST entries that are used by this table, as a bitmap
uint8_t used_ist_entries() const;
/// Dump debug information about the IDT to the console.
/// \arg index Which entry to print, or -1 for all entries
void dump(unsigned index = -1) const;
/// Get the global IDT
static IDT & get();
private:
void set(uint8_t i, void (*handler)(), uint16_t selector, uint8_t flags);
struct descriptor
{
uint16_t base_low;
uint16_t selector;
uint8_t ist;
uint8_t flags;
uint16_t base_mid;
uint32_t base_high;
uint32_t reserved; // must be zero
} __attribute__ ((packed, aligned(16)));
struct ptr
{
uint16_t limit;
descriptor *base;
} __attribute__ ((packed, aligned(4)));
descriptor m_entries[256];
ptr m_ptr;
};