mirror of
https://github.com/justinian/jsix.git
synced 2025-12-11 08:54:31 -08:00
This is the first of two rather big changes to clean up includes throughout the project. In this commit, the implicit semi-dependency on libc that bonnibel adds to every module is removed. Previously, I was sloppy with includes of libc headers and include directory order. Now, the freestanding headers from libc are split out into libc_free, and an implicit real dependency is added onto this module, unless `no_libc` is set to `True`. The full libc needs to be explicitly specified as a dependency to be used. Several things needed to change in order to do this: - Many places use `memset` or `memcpy` that cannot depend on libc. The kernel has basic implementations of them itself for this reason. Now those functions are moved into the lower-level `j6/memutils.h`, and libc merely references them. Other modules are now free to reference those functions from libj6 instead. - The kernel's `assert.h` was renamed kassert.h (matching its `kassert` function) so that the new `util/assert.h` can use `__has_include` to detect it and make sure the `assert` macro is usable in libutil code. - Several implementation header files under `__libj6/` also moved under the new libc_free. - A new `include_phase` property has been added to modules for Bonnibel, which can be "normal" (default) or "late" which uses `-idirafter` instead of `-I` for includes. - Since `<utility>` and `<new>` are not freestanding, implementations of `remove_reference`, `forward`, `move`, and `swap` were added to the `util` namespace to replace those from `std`, and `util/new.h` was added to declare `operator new` and `operator delete`.
157 lines
3.8 KiB
C++
157 lines
3.8 KiB
C++
#include <j6/memutils.h>
|
|
#include <util/no_construct.h>
|
|
|
|
#include "cpu.h"
|
|
#include "idt.h"
|
|
#include "logger.h"
|
|
|
|
extern "C" {
|
|
void idt_write(const void *idt_ptr);
|
|
|
|
#define ISR(i, s, name) extern void name ();
|
|
#define NISR(i, s, name)
|
|
#define EISR(i, s, name) extern void name ();
|
|
#define IRQ(i, q, name) extern void name ();
|
|
#include "interrupt_isrs.inc"
|
|
#undef IRQ
|
|
#undef NISR
|
|
#undef EISR
|
|
#undef ISR
|
|
}
|
|
|
|
// The BSP's IDT is initialized _before_ global constructors are called,
|
|
// so we don't want it to have a global constructor, lest it overwrite
|
|
// the previous initialization.
|
|
static util::no_construct<IDT> __g_bsp_idt_storage;
|
|
IDT &g_bsp_idt = __g_bsp_idt_storage.value;
|
|
void (*__nmi_handler)();
|
|
|
|
void
|
|
IDT::set_nmi_handler(uintptr_t address)
|
|
{
|
|
__nmi_handler = reinterpret_cast<void(*)()>(address);
|
|
}
|
|
|
|
IDT::IDT()
|
|
{
|
|
memset(this, 0, sizeof(IDT));
|
|
m_ptr.limit = sizeof(m_entries) - 1;
|
|
m_ptr.base = &m_entries[0];
|
|
|
|
#define ISR(i, s, name) set(i, & name, 0x08, 0x8e);
|
|
#define EISR(i, s, name) set(i, & name, 0x08, 0x8e);
|
|
#define IRQ(i, q, name) set(i, & name, 0x08, 0x8e);
|
|
#define NISR(i, s, name) set(i, __nmi_handler, 0x08, 0x8e);
|
|
#include "interrupt_isrs.inc"
|
|
#undef NISR
|
|
#undef IRQ
|
|
#undef EISR
|
|
#undef ISR
|
|
}
|
|
|
|
IDT &
|
|
IDT::current()
|
|
{
|
|
cpu_data &cpu = current_cpu();
|
|
return *cpu.idt;
|
|
}
|
|
|
|
void
|
|
IDT::install() const
|
|
{
|
|
idt_write(static_cast<const void*>(&m_ptr));
|
|
}
|
|
|
|
void
|
|
IDT::add_ist_entries()
|
|
{
|
|
#define ISR(i, s, name) if (s) { set_ist(i, s); }
|
|
#define NISR(i, s, name) if (s) { set_ist(i, s); }
|
|
#define EISR(i, s, name) if (s) { set_ist(i, s); }
|
|
#define IRQ(i, q, name)
|
|
#include "interrupt_isrs.inc"
|
|
#undef IRQ
|
|
#undef NISR
|
|
#undef EISR
|
|
#undef ISR
|
|
}
|
|
|
|
uint8_t
|
|
IDT::used_ist_entries()
|
|
{
|
|
constexpr uint8_t entries =
|
|
|
|
#define ISR(i, s, name) ((s) ? (1 << s) : 0) |
|
|
#define NISR(i, s, name) ((s) ? (1 << s) : 0) |
|
|
#define EISR(i, s, name) ((s) ? (1 << s) : 0) |
|
|
#define IRQ(i, q, name)
|
|
#include "interrupt_isrs.inc"
|
|
#undef IRQ
|
|
#undef NISR
|
|
#undef EISR
|
|
#undef ISR
|
|
|
|
0;
|
|
|
|
return entries;
|
|
}
|
|
|
|
void
|
|
IDT::set(uint8_t i, void (*handler)(), uint16_t selector, uint8_t flags)
|
|
{
|
|
uintptr_t addr = reinterpret_cast<uintptr_t>(handler);
|
|
|
|
m_entries[i].base_low = addr & 0xffff;
|
|
m_entries[i].base_mid = (addr >> 16) & 0xffff;
|
|
m_entries[i].base_high = (addr >> 32) & 0xffffffff;
|
|
m_entries[i].selector = selector;
|
|
m_entries[i].flags = flags;
|
|
m_entries[i].ist = 0;
|
|
m_entries[i].reserved = 0;
|
|
}
|
|
|
|
void
|
|
IDT::dump(unsigned index) const
|
|
{
|
|
unsigned start = 0;
|
|
unsigned count = (m_ptr.limit + 1) / sizeof(descriptor);
|
|
if (index != -1) {
|
|
start = index;
|
|
count = 1;
|
|
log::info(logs::boot, "IDT FOR INDEX %02x", index);
|
|
} else {
|
|
log::info(logs::boot, "Loaded IDT at: %lx size: %d bytes", m_ptr.base, m_ptr.limit+1);
|
|
}
|
|
|
|
const descriptor *idt =
|
|
reinterpret_cast<const descriptor *>(m_ptr.base);
|
|
|
|
for (int i = start; i < start+count; ++i) {
|
|
uint64_t base =
|
|
(static_cast<uint64_t>(idt[i].base_high) << 32) |
|
|
(static_cast<uint64_t>(idt[i].base_mid) << 16) |
|
|
idt[i].base_low;
|
|
|
|
char const *type;
|
|
switch (idt[i].flags & 0xf) {
|
|
case 0x5: type = " 32tsk "; break;
|
|
case 0x6: type = " 16int "; break;
|
|
case 0x7: type = " 16trp "; break;
|
|
case 0xe: type = " 32int "; break;
|
|
case 0xf: type = " 32trp "; break;
|
|
default: type = " ????? "; break;
|
|
}
|
|
|
|
if (idt[i].flags & 0x80) {
|
|
log::spam(logs::boot,
|
|
" Entry %3d: Base:%lx Sel(rpl %d, ti %d, %3d) IST:%d %s DPL:%d", i, base,
|
|
(idt[i].selector & 0x3),
|
|
((idt[i].selector & 0x4) >> 2),
|
|
(idt[i].selector >> 3),
|
|
idt[i].ist,
|
|
type,
|
|
((idt[i].flags >> 5) & 0x3));
|
|
}
|
|
}
|
|
}
|