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`.
82 lines
2.5 KiB
C++
82 lines
2.5 KiB
C++
#pragma once
|
|
/// \file idt.h
|
|
/// Definitions relating to a CPU's IDT table
|
|
#include <stdint.h>
|
|
#include "kassert.h"
|
|
|
|
class IDT
|
|
{
|
|
public:
|
|
IDT();
|
|
|
|
/// Get the currently running CPU's IDT
|
|
static IDT & current();
|
|
|
|
/// Set the global NMI handler. Must happen before creating
|
|
/// any IDTs.
|
|
static void set_nmi_handler(uintptr_t address);
|
|
|
|
/// 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, clearing it in the process.
|
|
/// \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) {
|
|
return __atomic_exchange_n(&m_entries[i].ist, 0, __ATOMIC_SEQ_CST);
|
|
}
|
|
|
|
/// Restore the IST entry used by an entry when done using it.
|
|
/// \arg i Which IDT entry to restore
|
|
/// \arg ist The IST index for entry i, or 0 for none
|
|
inline void return_ist(uint8_t i, uint8_t ist) {
|
|
if (!ist) return;
|
|
uint8_t expected = 0;
|
|
bool result = __atomic_compare_exchange_n(
|
|
&m_entries[i].ist, &expected, ist,
|
|
false, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST);
|
|
kassert(result, "Tried to overwrite a non-zero IST value in IDT");
|
|
}
|
|
|
|
/// Set the IST entry used by an entry. This should not be called
|
|
/// by interrupt handlers.
|
|
/// \arg i Which IDT entry to set
|
|
/// \arg ist The IST index for entry i, or 0 for none
|
|
inline 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
|
|
static uint8_t used_ist_entries();
|
|
|
|
/// 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);
|
|
|
|
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;
|
|
};
|