150 lines
6.5 KiB
C++
150 lines
6.5 KiB
C++
|
|
#pragma once
|
|
|
|
#if !defined(BAD_APPLE_OS_INTERRUPT_HPP_INCLUDED)
|
|
#define BAD_APPLE_OS_INTERRUPT_HPP_INCLUDED
|
|
|
|
#include <array>
|
|
#include <bit>
|
|
#include <cstdint>
|
|
|
|
namespace baos
|
|
{
|
|
#if defined(__x86_64__)
|
|
inline constexpr std::uint8_t INTERRUPT_DIVISION_ERROR = 0x00;
|
|
inline constexpr std::uint8_t INTERRUPT_OVERFLOW = 0x04;
|
|
inline constexpr std::uint8_t INTERRUPT_BOUND_RANGE_EXCEEDED = 0x05;
|
|
inline constexpr std::uint8_t INTERRUPT_INVALID_OPCODE = 0x06;
|
|
inline constexpr std::uint8_t INTERRUPT_DEVICE_NOT_AVAILABLE = 0x07;
|
|
inline constexpr std::uint8_t INTERRUPT_DOUBLE_FAULT = 0x08;
|
|
inline constexpr std::uint8_t INTERRUPT_INVALID_TSS = 0x0A;
|
|
inline constexpr std::uint8_t INTERRUPT_SEGMENT_NOT_PRESENT = 0x0B;
|
|
inline constexpr std::uint8_t INTERRUPT_STACK_SEGMENT_FAULT = 0x0C;
|
|
inline constexpr std::uint8_t INTERRUPT_GENERAL_PROTECTION_FAULT = 0x0D;
|
|
inline constexpr std::uint8_t INTERRUPT_PAGE_FAULT = 0x0E;
|
|
inline constexpr std::uint8_t INTERRUPT_X87_FP_EXCEPTION = 0x10;
|
|
inline constexpr std::uint8_t INTERRUPT_ALIGNMENT_CHECK = 0x11;
|
|
inline constexpr std::uint8_t INTERRUPT_MACHINE_CHECK = 0x12;
|
|
inline constexpr std::uint8_t INTERRUPT_SIMD_FP_EXCEPTION = 0x13;
|
|
inline constexpr std::uint8_t INTERRUPT_VIRTUALIZATION_EXCEPTION = 0x14;
|
|
inline constexpr std::uint8_t INTERRUPT_CONTROL_PROTECTION_EXCEPTION = 0x15;
|
|
|
|
struct InterruptFrame
|
|
{
|
|
std::uint64_t ip;
|
|
std::uint64_t cs;
|
|
std::uint64_t flags;
|
|
std::uint64_t sp;
|
|
std::uint64_t ss;
|
|
};
|
|
using interrupt_error_code_t = std::uint64_t;
|
|
|
|
enum class InterruptGateType
|
|
{
|
|
NONE = 0,
|
|
INTERRUPT_GATE = 0xE,
|
|
TRAP_GATE = 0xF
|
|
};
|
|
|
|
enum class InterruptSelectorTable
|
|
{
|
|
GDT = 0,
|
|
LDT = 1
|
|
};
|
|
|
|
struct InterruptDescriptor
|
|
{
|
|
/* 0 */ unsigned offsetLow : 16 = 0;
|
|
/* 16 */ unsigned selectorPrivilegeLevel : 2 = 0;
|
|
/* 18 */ InterruptSelectorTable selectorTable : 1 = InterruptSelectorTable::GDT;
|
|
/* 19 */ unsigned selectorIndex : 13 = 0;
|
|
/* 32 */ unsigned interruptStackTable : 3 = 0;
|
|
/* 35 */ unsigned reserved0_ : 5 = 0;
|
|
/* 40 */ InterruptGateType gateType : 4 = InterruptGateType::NONE;
|
|
/* 44 */ unsigned reserved1_ : 1 = 0;
|
|
/* 45 */ unsigned privilegeLevel : 2 = 0;
|
|
/* 47 */ bool present : 1 = 0;
|
|
/* 48 */ unsigned long offsetHigh : 48 = 0;
|
|
/* 96 */ unsigned reserved2_ : 32 = 0;
|
|
} __attribute__((packed));
|
|
|
|
class InterruptDescriptorTable
|
|
{
|
|
private:
|
|
alignas(16) std::array<InterruptDescriptor, 256> mDescriptors;
|
|
public:
|
|
inline void install() const noexcept;
|
|
|
|
template<typename THandler>
|
|
void setupInterrupt(std::uint8_t index, THandler handler) noexcept
|
|
{
|
|
const std::uint64_t offset = std::bit_cast<std::uint64_t>(handler);
|
|
mDescriptors[index] = InterruptDescriptor{
|
|
.offsetLow = static_cast<unsigned>(offset & 0xFFFF),
|
|
.selectorPrivilegeLevel = 0,
|
|
.selectorIndex = 1, // kernel code
|
|
.interruptStackTable = 0,
|
|
.gateType = InterruptGateType::INTERRUPT_GATE,
|
|
.privilegeLevel = 0,
|
|
.present = true,
|
|
.offsetHigh = (offset >> 16)
|
|
};
|
|
}
|
|
|
|
inline void setupErrorInterrupts() noexcept;
|
|
};
|
|
#endif
|
|
|
|
using interrupt_handler_t = __attribute__((interrupt)) void(*)(baos::InterruptFrame*);
|
|
using interrupt_handler_with_error_code_t = __attribute__((interrupt)) void(*)(baos::InterruptFrame*, interrupt_error_code_t);
|
|
|
|
__attribute__((interrupt))
|
|
void isrDivisionError(InterruptFrame* interruptFrame) noexcept;
|
|
|
|
__attribute__((interrupt)) void isrOverflow(InterruptFrame* interruptFrame) noexcept;
|
|
__attribute__((interrupt)) void isrBoundRangeExceeded(InterruptFrame* interruptFrame) noexcept;
|
|
__attribute__((interrupt)) void isrInvalidOpCode(InterruptFrame* interruptFrame) noexcept;
|
|
__attribute__((interrupt)) void isrDeviceNotAvailable(InterruptFrame* interruptFrame) noexcept;
|
|
__attribute__((interrupt)) void isrDoubleFault(InterruptFrame* interruptFrame) noexcept;
|
|
__attribute__((interrupt)) void isrInvalidTSS(InterruptFrame* interruptFrame, interrupt_error_code_t errorCode) noexcept;
|
|
__attribute__((interrupt)) void isrSegmentNotPresent(InterruptFrame* interruptFrame, interrupt_error_code_t errorCode) noexcept;
|
|
__attribute__((interrupt)) void isrStackSegmentFault(InterruptFrame* interruptFrame, interrupt_error_code_t errorCode) noexcept;
|
|
__attribute__((interrupt)) void isrGeneralProtectionFault(InterruptFrame* interruptFrame, interrupt_error_code_t errorCode) noexcept;
|
|
__attribute__((interrupt)) void isrPageFault(InterruptFrame* interruptFrame, interrupt_error_code_t errorCode) noexcept;
|
|
__attribute__((interrupt)) void isrX87FPException(InterruptFrame* interruptFrame) noexcept;
|
|
__attribute__((interrupt)) void isrAlignmentCheck(InterruptFrame* interruptFrame, interrupt_error_code_t errorCode) noexcept;
|
|
__attribute__((interrupt)) void isrMachineCheck(InterruptFrame* interruptFrame) noexcept;
|
|
__attribute__((interrupt)) void isrSimdFpException(InterruptFrame* interruptFrame) noexcept;
|
|
__attribute__((interrupt)) void isrVirtualizationException(InterruptFrame* interruptFrame) noexcept;
|
|
__attribute__((interrupt)) void isrControlProtectionException(InterruptFrame* interruptFrame, interrupt_error_code_t errorCode) noexcept;
|
|
|
|
extern "C" void __setIDT(uint16_t limit, const void* base);
|
|
void InterruptDescriptorTable::install() const noexcept
|
|
{
|
|
__setIDT(sizeof(mDescriptors), &mDescriptors);
|
|
}
|
|
|
|
void InterruptDescriptorTable::setupErrorInterrupts() noexcept
|
|
{
|
|
setupInterrupt(INTERRUPT_DIVISION_ERROR, &isrDivisionError);
|
|
setupInterrupt(INTERRUPT_OVERFLOW, &isrOverflow);
|
|
setupInterrupt(INTERRUPT_BOUND_RANGE_EXCEEDED, &isrBoundRangeExceeded);
|
|
setupInterrupt(INTERRUPT_INVALID_OPCODE, &isrInvalidOpCode);
|
|
setupInterrupt(INTERRUPT_DEVICE_NOT_AVAILABLE, &isrDeviceNotAvailable);
|
|
setupInterrupt(INTERRUPT_DOUBLE_FAULT, &isrDoubleFault);
|
|
setupInterrupt(INTERRUPT_INVALID_TSS, &isrInvalidTSS);
|
|
setupInterrupt(INTERRUPT_SEGMENT_NOT_PRESENT, &isrSegmentNotPresent);
|
|
setupInterrupt(INTERRUPT_STACK_SEGMENT_FAULT, &isrStackSegmentFault);
|
|
setupInterrupt(INTERRUPT_GENERAL_PROTECTION_FAULT, &isrGeneralProtectionFault);
|
|
setupInterrupt(INTERRUPT_PAGE_FAULT, &isrPageFault);
|
|
setupInterrupt(INTERRUPT_X87_FP_EXCEPTION, &isrX87FPException);
|
|
setupInterrupt(INTERRUPT_ALIGNMENT_CHECK, &isrAlignmentCheck);
|
|
setupInterrupt(INTERRUPT_MACHINE_CHECK, &isrMachineCheck);
|
|
setupInterrupt(INTERRUPT_SIMD_FP_EXCEPTION, &isrSimdFpException);
|
|
setupInterrupt(INTERRUPT_VIRTUALIZATION_EXCEPTION, &isrVirtualizationException);
|
|
setupInterrupt(INTERRUPT_CONTROL_PROTECTION_EXCEPTION, &isrControlProtectionException);
|
|
}
|
|
}
|
|
|
|
#endif // !defined(BAD_APPLE_OS_INTERRUPT_HPP_INCLUDED)
|