diff --git a/targets/_any/SConscript b/targets/_any/SConscript index 7439416..572d10c 100644 --- a/targets/_any/SConscript +++ b/targets/_any/SConscript @@ -33,9 +33,10 @@ extern const unsigned {symbol}_SIZE; env.Command([f'{res}.s', f'{res}.hpp'.replace('src/', 'include/')], res, action = _generate_s) env.AddMethod(_resource, 'Resource') -irs_sources = Split(''' +isr_sources = Split(''' src/drivers/pic.cpp src/drivers/ps2.cpp + src/os/interrupt.cpp ''') any_target_sources = Split(''' src/app/main.cpp @@ -55,6 +56,6 @@ any_target_sources = Split(''' env.Resource(env.File('src/os/resources/lat9-08.psf').abspath, 'LAT9_08') env.Append(KERNEL_SOURCES = [env.File(f) for f in any_target_sources]) -env.Append(KERNEL_ISR_SOURCES = [env.File(f) for f in irs_sources]) +env.Append(KERNEL_ISR_SOURCES = [env.File(f) for f in isr_sources]) Return('env') \ No newline at end of file diff --git a/targets/_any/include/drivers/pic.hpp b/targets/_any/include/drivers/pic.hpp index 51def0f..3bd1d33 100644 --- a/targets/_any/include/drivers/pic.hpp +++ b/targets/_any/include/drivers/pic.hpp @@ -6,6 +6,7 @@ #include +#include "os/interrupt.hpp" #include "os/port.hpp" inline constexpr std::uint16_t PORT_PIC1 = 0x20; @@ -25,17 +26,4 @@ void unmaskIRQ(std::uint8_t irq) noexcept; return (offset & 7) == 0; } -#if defined(__x86_64__) -struct InterruptFrame -{ - std::uint64_t ip; - std::uint64_t cs; - std::uint64_t flags; - std::uint64_t sp; - std::uint64_t ss; -}; -#endif - -using interrupt_handler_t = __attribute__((interrupt)) void(*)(InterruptFrame*); - #endif // !defined(BAD_APPLE_OS_KERNEL_PIC_HPP_INCLUDED) diff --git a/targets/_any/include/os/interrupt.hpp b/targets/_any/include/os/interrupt.hpp new file mode 100644 index 0000000..447d8e9 --- /dev/null +++ b/targets/_any/include/os/interrupt.hpp @@ -0,0 +1,47 @@ + +#pragma once + +#if !defined(BAD_APPLE_OS_INTERRUPT_HPP_INCLUDED) +#define BAD_APPLE_OS_INTERRUPT_HPP_INCLUDED + +#include + +namespace baos +{ +#if defined(__x86_64__) +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; +#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; +} + +#endif // !defined(BAD_APPLE_OS_INTERRUPT_HPP_INCLUDED) diff --git a/targets/_any/src/os/draw.cpp b/targets/_any/src/os/draw.cpp index 5454583..ecb3666 100644 --- a/targets/_any/src/os/draw.cpp +++ b/targets/_any/src/os/draw.cpp @@ -24,7 +24,13 @@ void scrollVertical(int scrollY, const Pixel& fillColor) noexcept const size_t byteDist = scrollY * bytesPerRow; uint8_t* basePtr = reinterpret_cast(gDoubleBuffer.getBase()); std::memmove(basePtr, basePtr + byteDist, bytesToMove); - std::memset(basePtr + byteDist, 0, byteDist); + for (unsigned posY = gDoubleBuffer.getHeight() - scrollY; posY < gDoubleBuffer.getHeight(); ++posY) + { + for (unsigned posX = 0; posX < gDoubleBuffer.getWidth(); ++posX) + { + gDoubleBuffer.setPixel(posX, posY, fillColor); + } + } std::memcpy(gFramebuffer.getBase(), gDoubleBuffer.getBase(), gDoubleBuffer.getHeight() * bytesPerRow); } } diff --git a/targets/_any/src/os/interrupt.cpp b/targets/_any/src/os/interrupt.cpp new file mode 100644 index 0000000..1c7c6a2 --- /dev/null +++ b/targets/_any/src/os/interrupt.cpp @@ -0,0 +1,120 @@ + +#include "os/interrupt.hpp" +#include "os/serial.hpp" +#include "os/tty.hpp" + +namespace baos +{ +extern "C" [[noreturn]] void __halt(); + +__attribute__((no_caller_saved_registers)) +void handleException(const char* name, InterruptFrame* interruptFrame) noexcept +{ + tty::write(name); + serialWriteString(PORT_COM1, name); + __halt(); +} + +__attribute__((interrupt)) +void isrDivisionError(InterruptFrame* interruptFrame) noexcept +{ + handleException("division error", interruptFrame); +} + +__attribute__((interrupt)) +void isrOverflow(InterruptFrame* interruptFrame) noexcept +{ + handleException("Overflow", interruptFrame); +} + +__attribute__((interrupt)) +void isrBoundRangeExceeded(InterruptFrame* interruptFrame) noexcept +{ + handleException("BoundRangeExceeded", interruptFrame); +} + +__attribute__((interrupt)) +void isrInvalidOpCode(InterruptFrame* interruptFrame) noexcept +{ + handleException("InvalidOpCode", interruptFrame); +} + +__attribute__((interrupt)) +void isrDeviceNotAvailable(InterruptFrame* interruptFrame) noexcept +{ + handleException("DeviceNotAvailable", interruptFrame); +} + +__attribute__((interrupt)) +void isrDoubleFault(InterruptFrame* interruptFrame) noexcept +{ + handleException("DoubleFault", interruptFrame); +} + +__attribute__((interrupt)) +void isrInvalidTSS(InterruptFrame* interruptFrame, interrupt_error_code_t errorCode) noexcept +{ + handleException("InvalidTSS", interruptFrame); +} + +__attribute__((interrupt)) +void isrSegmentNotPresent(InterruptFrame* interruptFrame, interrupt_error_code_t errorCode) noexcept +{ + handleException("SegmentNotPresent", interruptFrame); +} + +__attribute__((interrupt)) +void isrStackSegmentFault(InterruptFrame* interruptFrame, interrupt_error_code_t errorCode) noexcept +{ + handleException("StackSegmentFault", interruptFrame); +} + +__attribute__((interrupt)) +void isrGeneralProtectionFault(InterruptFrame* interruptFrame, interrupt_error_code_t errorCode) noexcept +{ + handleException("GeneralProtectionFault", interruptFrame); +} + +__attribute__((interrupt)) +void isrPageFault(InterruptFrame* interruptFrame, interrupt_error_code_t errorCode) noexcept +{ + handleException("PageFault", interruptFrame); +} + +__attribute__((interrupt)) +void isrX87FPException(InterruptFrame* interruptFrame) noexcept +{ + handleException("X87FPException", interruptFrame); +} + +__attribute__((interrupt)) +void isrAlignmentCheck(InterruptFrame* interruptFrame, interrupt_error_code_t errorCode) noexcept +{ + handleException("AlignmentCheck", interruptFrame); +} + +__attribute__((interrupt)) +void isrMachineCheck(InterruptFrame* interruptFrame) noexcept +{ + handleException("MachineCheck", interruptFrame); +} + +__attribute__((interrupt)) +void isrSimdFpException(InterruptFrame* interruptFrame) noexcept +{ + handleException("SimdFpException", interruptFrame); +} + +__attribute__((interrupt)) +void isrVirtualizationException(InterruptFrame* interruptFrame) noexcept +{ + handleException("VirtualizationException", interruptFrame); +} + +__attribute__((interrupt)) +void isrControlProtectionException(InterruptFrame* interruptFrame, interrupt_error_code_t errorCode) noexcept +{ + handleException("ControlProtectionException", interruptFrame); +} + +} \ No newline at end of file diff --git a/targets/x86_64/src/kernel/boot.s b/targets/x86_64/src/kernel/boot.s index def8705..8e4fea6 100644 --- a/targets/x86_64/src/kernel/boot.s +++ b/targets/x86_64/src/kernel/boot.s @@ -41,9 +41,14 @@ _start: // We are done. Clear interrupts and halt. cli -.kernel_end: + +.global __halt +.type __halt @function +__halt: hlt - jmp .kernel_end + jmp __halt + + .global __setGDT .type __setGDT @function diff --git a/targets/x86_64/src/kernel/startup.cpp b/targets/x86_64/src/kernel/startup.cpp index adaa569..dc57f6a 100644 --- a/targets/x86_64/src/kernel/startup.cpp +++ b/targets/x86_64/src/kernel/startup.cpp @@ -27,6 +27,23 @@ constexpr std::uint8_t irqToInterrupt(std::uint8_t irq) noexcept } return SLAVE_PIC_OFFSET + irq; } +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; inline constexpr std::uint8_t INTERRUPT_KEYBOARD = irqToInterrupt(1); constinit std::array GDT alignas(16) = { @@ -117,7 +134,8 @@ extern "C" void __setGDT(uint16_t limit, void* base); extern "C" void __setIDT(uint16_t limit, void* base); extern "C" void __reloadSegments(uint64_t code, uint64_t data); -void setupInterrupt(std::uint8_t index, interrupt_handler_t handler, std::uint8_t flags) noexcept +template +void setupInterrupt(std::uint8_t index, THandler handler) noexcept { const std::uint64_t offset = std::bit_cast(handler); IDT[index] = InterruptDescriptor{ @@ -139,13 +157,28 @@ EfiBootInfo* gBootInfo; void main(); -extern void __isr21(InterruptFrame*); - void kernel_main() { using namespace baos; - setupInterrupt(INTERRUPT_KEYBOARD, &ps2::isrKeyboard, 0); + setupInterrupt(INTERRUPT_DIVISION_ERROR, &baos::isrDivisionError); + setupInterrupt(INTERRUPT_OVERFLOW, &baos::isrOverflow); + setupInterrupt(INTERRUPT_BOUND_RANGE_EXCEEDED, &baos::isrBoundRangeExceeded); + setupInterrupt(INTERRUPT_INVALID_OPCODE, &baos::isrInvalidOpCode); + setupInterrupt(INTERRUPT_DEVICE_NOT_AVAILABLE, &baos::isrDeviceNotAvailable); + setupInterrupt(INTERRUPT_DOUBLE_FAULT, &baos::isrDoubleFault); + setupInterrupt(INTERRUPT_INVALID_TSS, &baos::isrInvalidTSS); + setupInterrupt(INTERRUPT_SEGMENT_NOT_PRESENT, &baos::isrSegmentNotPresent); + setupInterrupt(INTERRUPT_STACK_SEGMENT_FAULT, &baos::isrStackSegmentFault); + setupInterrupt(INTERRUPT_GENERAL_PROTECTION_FAULT, &baos::isrGeneralProtectionFault); + setupInterrupt(INTERRUPT_PAGE_FAULT, &baos::isrPageFault); + setupInterrupt(INTERRUPT_X87_FP_EXCEPTION, &baos::isrX87FPException); + setupInterrupt(INTERRUPT_ALIGNMENT_CHECK, &baos::isrAlignmentCheck); + setupInterrupt(INTERRUPT_MACHINE_CHECK, &baos::isrMachineCheck); + setupInterrupt(INTERRUPT_SIMD_FP_EXCEPTION, &baos::isrSimdFpException); + setupInterrupt(INTERRUPT_VIRTUALIZATION_EXCEPTION, &baos::isrVirtualizationException); + setupInterrupt(INTERRUPT_CONTROL_PROTECTION_EXCEPTION, &baos::isrControlProtectionException); + setupInterrupt(INTERRUPT_KEYBOARD, &ps2::isrKeyboard); __setGDT(sizeof(GDT), &GDT); __setIDT(sizeof(IDT), &IDT);