feat: implement core initialization and local APIC setup
This commit is contained in:
parent
ada1859910
commit
beb7fb38ae
19 changed files with 747 additions and 41 deletions
|
|
@ -10,7 +10,6 @@ namespace acpi {
|
|||
struct discovery_result_t {
|
||||
optional<Rsdp> rsdp;
|
||||
optional<Madt> madt;
|
||||
// TODO(wiring): capture the FADT in setupAcpi and store it here
|
||||
optional<Fadt> fadt;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -2,6 +2,28 @@
|
|||
|
||||
#include "memory/pointer.h"
|
||||
|
||||
#include "acpi/discovery.h"
|
||||
#include "memory/pagetable.h"
|
||||
|
||||
namespace apic {
|
||||
void startupCore(paddr_t code, paddr_t stack);
|
||||
}
|
||||
|
||||
struct stack_t {
|
||||
paddr_t ptr;
|
||||
size_t size;
|
||||
};
|
||||
|
||||
using core_id = uint8_t;
|
||||
|
||||
struct Core {
|
||||
core_id id;
|
||||
stack_t stack;
|
||||
PageTable kernelPageTable;
|
||||
};
|
||||
|
||||
optional<Core> initCore(acpi::Madt madt, core_id id);
|
||||
|
||||
void initCores(acpi::discovery_result_t);
|
||||
|
||||
void transitionStartupCore();
|
||||
|
||||
} // namespace apic
|
||||
24
kernel/include/apic/lapic.h
Normal file
24
kernel/include/apic/lapic.h
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
#pragma once
|
||||
|
||||
#include "acpi/discovery.h"
|
||||
#include "util/number.h"
|
||||
|
||||
namespace apic {
|
||||
|
||||
using lapic_id_t = uint32_t;
|
||||
|
||||
void initLocalApic(const acpi::discovery_result_t& discovery);
|
||||
|
||||
lapic_id_t localApicId();
|
||||
|
||||
void sendInit(lapic_id_t destination);
|
||||
|
||||
// startup_page: physical address of the real-mode entry point divided by 4096;
|
||||
// must point below 1 MiB, so only values < 0x100 are meaningful.
|
||||
void sendStartup(lapic_id_t destination, uint8_t startup_page);
|
||||
|
||||
void sendInterrupt(lapic_id_t destination, uint8_t vector);
|
||||
|
||||
void signalEndOfInterrupt();
|
||||
|
||||
} // namespace apic
|
||||
|
|
@ -33,6 +33,26 @@ constexpr duration_t operator*(uint64_t scalar, duration_t duration) {
|
|||
return duration_t{duration.timer_count * scalar};
|
||||
}
|
||||
|
||||
constexpr bool operator==(duration_t left, duration_t right) {
|
||||
return left.timer_count == right.timer_count;
|
||||
}
|
||||
|
||||
constexpr bool operator<(duration_t left, duration_t right) {
|
||||
return left.timer_count < right.timer_count;
|
||||
}
|
||||
|
||||
constexpr bool operator<=(duration_t left, duration_t right) {
|
||||
return left.timer_count <= right.timer_count;
|
||||
}
|
||||
|
||||
constexpr bool operator>(duration_t left, duration_t right) {
|
||||
return left.timer_count > right.timer_count;
|
||||
}
|
||||
|
||||
constexpr bool operator>=(duration_t left, duration_t right) {
|
||||
return left.timer_count >= right.timer_count;
|
||||
}
|
||||
|
||||
constexpr timestamp_t operator+(timestamp_t timestamp, duration_t duration) {
|
||||
return timestamp_t{timestamp.timer_count + duration.timer_count};
|
||||
}
|
||||
|
|
@ -62,9 +82,4 @@ void busyWait(duration_t duration);
|
|||
|
||||
timestamp_t now();
|
||||
|
||||
// TODO: when dynamic allocation and lists are available
|
||||
// struct Timer {};
|
||||
//
|
||||
// Timer getCoreTimerInstance();
|
||||
|
||||
} // namespace apic
|
||||
|
|
|
|||
58
kernel/include/cpu/gdt.h
Normal file
58
kernel/include/cpu/gdt.h
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
#pragma once
|
||||
|
||||
#include "memory/pointer.h"
|
||||
#include "util/optional.h"
|
||||
|
||||
struct [[gnu::packed]] gdt_register_t {
|
||||
uint16_t limit;
|
||||
uint64_t base;
|
||||
};
|
||||
static_assert(sizeof(gdt_register_t) == 10);
|
||||
|
||||
struct Gdt {
|
||||
using selector_t = uint16_t;
|
||||
|
||||
enum class segment_type_t : uint8_t {
|
||||
code,
|
||||
data,
|
||||
task_state,
|
||||
};
|
||||
|
||||
struct flags_t {
|
||||
segment_type_t type;
|
||||
uint8_t privilege_level;
|
||||
bool long_mode;
|
||||
bool default_operand_32bit;
|
||||
bool granularity_4KiB;
|
||||
bool readable_writeable;
|
||||
};
|
||||
|
||||
struct segment_t {
|
||||
flags_t flags;
|
||||
uint64_t base;
|
||||
uint32_t limit;
|
||||
};
|
||||
|
||||
static Gdt fromCurrent();
|
||||
static optional<Gdt> allocNew();
|
||||
|
||||
void activate();
|
||||
optional<selector_t> add(segment_t segment);
|
||||
optional<segment_t> get(selector_t selector);
|
||||
|
||||
paddr_t base;
|
||||
uint16_t limit;
|
||||
};
|
||||
|
||||
struct [[gnu::packed]] tss_t {
|
||||
uint32_t reserved0;
|
||||
uint64_t rsp[3];
|
||||
uint64_t reserved1;
|
||||
uint64_t ist[7];
|
||||
uint64_t reserved2;
|
||||
uint16_t reserved3;
|
||||
uint16_t iomap_base;
|
||||
};
|
||||
static_assert(sizeof(tss_t) == 104);
|
||||
|
||||
void reloadSegments(Gdt::selector_t code_selector, Gdt::selector_t data_selector);
|
||||
3
kernel/include/main.h
Normal file
3
kernel/include/main.h
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
#pragma once
|
||||
|
||||
[[noreturn]] void main();
|
||||
|
|
@ -12,10 +12,17 @@ struct PhysicalAllocator {
|
|||
size_t page_count;
|
||||
};
|
||||
|
||||
enum class address_range_t : uint8_t {
|
||||
any,
|
||||
below_4gib,
|
||||
};
|
||||
|
||||
static void init(const multiboot::tag_mmap* multiboot_info);
|
||||
static PhysicalAllocator& getInstance();
|
||||
|
||||
optional<allocation_t> allocPages(size_t page_count, size_t alignment_pages = 1);
|
||||
optional<allocation_t> allocPages(
|
||||
size_t page_count, size_t alignment_pages = 1, address_range_t range = address_range_t::any
|
||||
);
|
||||
void free(allocation_t ptr);
|
||||
bool force(allocation_t ptr, bool free);
|
||||
|
||||
|
|
|
|||
|
|
@ -25,12 +25,12 @@ struct PageTable {
|
|||
};
|
||||
|
||||
static PageTable fromCurrent();
|
||||
static optional<PageTable> allocNew();
|
||||
|
||||
void activate();
|
||||
bool map(void* vaddress, paddr_t paddress, flags_t flags);
|
||||
void unmap(void* vaddress);
|
||||
optional<info_t> get(void* vaddress);
|
||||
|
||||
private:
|
||||
paddr_t l4;
|
||||
};
|
||||
16
kernel/include/util/msr.h
Normal file
16
kernel/include/util/msr.h
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
#pragma once
|
||||
|
||||
#include "util/number.h"
|
||||
|
||||
inline uint64_t msr_read(uint32_t msr) {
|
||||
uint32_t low = 0;
|
||||
uint32_t high = 0;
|
||||
__asm__ volatile("rdmsr" : "=a"(low), "=d"(high) : "c"(msr));
|
||||
return (static_cast<uint64_t>(high) << 32) | low;
|
||||
}
|
||||
|
||||
inline void msr_write(uint32_t msr, uint64_t value) {
|
||||
uint32_t low = static_cast<uint32_t>(value);
|
||||
uint32_t high = static_cast<uint32_t>(value >> 32);
|
||||
__asm__ volatile("wrmsr" : : "c"(msr), "a"(low), "d"(high));
|
||||
}
|
||||
|
|
@ -131,7 +131,7 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
operator bool() const {
|
||||
explicit operator bool() const {
|
||||
return initialized;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue