[kernel] Start all other processors in the system
This very large commit is mainly focused on getting the APs started and to a state where they're waiting to have work scheduled. (Actually scheduling on them is for another commit.) To do this, a bunch of major changes were needed: - Moving a lot of the CPU initialization (including for the BSP) to init_cpu(). This includes setting up IST stacks, writing MSRs, and creating the cpu_data structure. For the APs, this also creates and installs the GDT and TSS, and installs the global IDT. - Creating the AP startup code, which tries to be as position independent as possible. It's copied from its location to 0x8000 for AP startup, and some of it is fixed at that address. The AP startup code jumps from real mode to long mode with paging in one swell foop. - Adding limited IPI capability to the lapic class. This will need to improve. - Renaming cpu/cpu.* to cpu/cpu_id.* because it was just annoying in GDB and really isn't anything but cpu_id anymore. - Moved all the GDT, TSS, and IDT code into their own files and made them classes instead of a mess of free functions. - Got rid of bsp_cpu_data everywhere. Now always call the new current_cpu() to get the current CPU's cpu_data. - Device manager keeps a list of APIC ids now. This should go somewhere else eventually, device_manager needs to be refactored away. - Moved some more things (notably the g_kernel_stacks vma) to the pre-constructor setup in memory_bootstrap. That whole file is in bad need of a refactor.
This commit is contained in:
61
src/kernel/idt.h
Normal file
61
src/kernel/idt.h
Normal file
@@ -0,0 +1,61 @@
|
||||
#pragma once
|
||||
/// \file idt.h
|
||||
/// Definitions relating to a CPU's IDT table
|
||||
#include <stdint.h>
|
||||
|
||||
class IDT
|
||||
{
|
||||
public:
|
||||
static constexpr unsigned count = 256;
|
||||
|
||||
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(unsigned i) const {
|
||||
if (i >= count) return 0;
|
||||
return m_entries[i].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;
|
||||
|
||||
private:
|
||||
void set(uint8_t i, void (*handler)(), uint16_t selector, uint8_t flags);
|
||||
void set_ist(uint8_t i, uint8_t ist);
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
extern IDT &g_idt;
|
||||
Reference in New Issue
Block a user