x86: add basic interrupt support

This commit also fixes the fun little size bug in
segment.S where i subtracted the end from the
start address of the GDT instead of the other way
round which resulted in a gigantic overflow :)
main
anna 3 years ago
parent 347bb5cc9c
commit 613c28a965
Signed by: fef
GPG Key ID: EC22E476DC2D3D84

@ -7,6 +7,7 @@ target_link_libraries(gay_arch PRIVATE c gay_kernel)
add_subdirectory(boot)
add_subdirectory(mm)
add_subdirectory(sys)
# This file is part of GayBSD.
# Copyright (c) 2021 fef <owo@fef.moe>.

@ -2,8 +2,10 @@
#include <string.h>
#include <arch/interrupt.h>
#include <arch/multiboot.h>
#include <gay/cdefs.h>
#include <gay/config.h>
#include <gay/kprintf.h>
#include <gay/mm.h>
@ -37,10 +39,10 @@ struct fb_cell {
u8 c;
enum vga_color fg:4;
enum vga_color bg:4;
};
} __packed;
/* struct fb_cell gets aligned to 4 bytes for some reason, so we need to use u16 internally */
static volatile u16 *const framebuffer = (volatile u16 *)FB_ADDRESS;
/** @brief BIOS provided character framebuffer */
static volatile struct fb_cell *const framebuffer = (volatile struct fb_cell *)FB_ADDRESS;
/** @brief current line in the framebuffer */
static unsigned int fb_line;
/** @brief current column in the framebuffer */
@ -50,7 +52,7 @@ enum vga_color fb_background;
/** @brief current foreground color */
enum vga_color fb_foreground;
static volatile struct fb_cell *cell_at(unsigned int line, unsigned int col);
#define cell_at(line, col) ( &framebuffer[(line) * FB_COLS + (col)] )
#define current_cell (cell_at(fb_line, fb_col))
static ssize_t fb_write(struct kprintf_renderer *renderer, const void *buf, size_t size);
@ -71,13 +73,14 @@ static void handle_mmap_tag(struct mb2_tag_mmap *tag);
static const char *mmap_type_name(u32 type);
extern int main(int argc, char *argv[]);
extern void _start(void);
void _boot(u32 magic, void *address)
__asmlink void _boot(u32 magic, void *address) /* NOLINT */
{
kprintf_set_renderer(&fb_kprintf_renderer);
fb_init(VGA_COLOR_LIGHT_GREY, VGA_COLOR_BLACK);
x86_setup_interrupts();
if (magic != MB2_BOOTLOADER_MAGIC) {
kprintf("Error: invalid bootloader magic, aborting\n");
return;
@ -102,6 +105,9 @@ static inline void handle_tag(struct mb2_tag *tag)
switch (tag->type) {
case MB2_TAG_TYPE_END:
break;
case MB2_TAG_TYPE_CMDLINE:
kprintf("Kernel command line: %s\n", ((struct mb2_tag_string *)tag)->string);
break;
case MB2_TAG_TYPE_MMAP:
handle_mmap_tag((struct mb2_tag_mmap *)tag);
break;
@ -138,7 +144,8 @@ static inline void handle_mmap_tag(struct mb2_tag_mmap *tag)
while (1);
}
if (kmalloc_init(region, region + region_len) != 0) {
int err = kmalloc_init((uintptr_t)region, (uintptr_t)(region + region_len));
if (err) {
kprintf("kmalloc_init() failed! Aborting.\n");
while (1);
}
@ -213,8 +220,8 @@ static void fb_init(enum vga_color fg, enum vga_color bg)
{
fb_line = 0;
fb_col = 0;
fb_foreground = VGA_COLOR_LIGHT_GREY;
fb_background = VGA_COLOR_BLACK;
fb_foreground = fg;
fb_background = bg;
fb_clear();
}
@ -262,13 +269,9 @@ static const char *mmap_type_name(u32 type)
return "NVS";
case MB2_MEMORY_BADRAM:
return "Bad RAM";
default:
return "Unknown";
}
return "Unknown";
}
static inline volatile struct fb_cell *cell_at(unsigned int line, unsigned int col)
{
return (volatile struct fb_cell *)&framebuffer[line * FB_COLS + col];
}
/*

@ -115,6 +115,9 @@ header_end:
#define phys_addr(c_symbol) (c_symbol - CFG_KERNEL_RELOCATE)
ASM_ENTRY(_start)
/* interrupts are disabled until we set up the IDT in x86_setup_idt() */
cli
/*
* The kernel image starts at 1 MiB into physical memory.
* We currently assume the kernel is < 3 MiB
@ -180,13 +183,13 @@ ASM_ENTRY(_start)
* because they are page aligned so they are used as flags for the MMU,
* see ../include/arch/page.h).
*
* The offset added to pd0 is the page number multiplied with the low_size
* of a single entry (a pointer size):
* (0x00000000 / PAGE_SIZE) / 1024 entries in a page table = 0
* (0xc0000000 / PAGE_SIZE) / 1024 entries in a page table = 786
* The offset added to pd0 is the page table number multiplied with the
* size of a page directory entry (4 bytes). The page table number can
* be calculated by dividing the number of the first page it maps
* through the total number of entries in the page directory.
*/
movl $(phys_addr(pt0) + 0x003), phys_addr(pd0) + 0 * 4 /* 0x00000000 */
movl $(phys_addr(pt0) + 0x003), phys_addr(pd0) + 768 * 4 /* 0xc0000000 */
movl $(phys_addr(pt0) + 0x003), phys_addr(pd0) + (( 0x00000000 / PAGE_SIZE) / 1024) * 4
movl $(phys_addr(pt0) + 0x003), phys_addr(pd0) + ((CFG_KERNEL_RELOCATE / PAGE_SIZE) / 1024) * 4
/*
* The last entry in the page directory points to itself.
@ -226,6 +229,7 @@ ASM_END(_start)
.text
.extern x86_replace_gdt
.extern x86_load_idt
ASM_ENTRY(_start_virtual)
@ -255,7 +259,7 @@ ASM_ENTRY(_start_virtual)
/*
* but before we call _boot(), we replace the GDT provided by GRUB
* with our own (see arch/mm/segment.S)
* with our own (arch/mm/segment.S) and load the IDT (arch/sys/idt.S).
*/
call x86_replace_gdt
call _boot

@ -0,0 +1,138 @@
/* See the end of this file for copyright and license terms. */
#pragma once
/** @brief Total number of interrupt lines on x86. */
#define X86_INTR_COUNT 256
/*
* These are all reserved interrupt/exception vector numbers for x86 Protected Mode.
* Taken from the Intel Architecture Software Developer's Manual, vol. 3, table 6-1.
*/
/** @brief Divide Error */
#define X86_VECT_DE 0
/** @brief Debug Exception */
#define X86_VECT_DB 1
/** @brief Nonmaskable Interrupt */
#define X86_VECT_NMI 2
/** @brief Breakpoint */
#define X86_VECT_BP 3
/** @brief Overflow */
#define X86_VECT_OF 4
/** @brief BOUND Range Exceeded */
#define X86_VECT_BR 5
/** @brief Invalid Opcode (Undefined Opcode) */
#define X86_VECT_UD 6
/** @brief Device Not Available (No Math Coprocessor) */
#define X86_VECT_NM 7
/** @brief Double Fault */
#define X86_VECT_DF 8
/* 9 is reserved (Coprocessor Segment Overrun) */
/** @brief Invalid TSS */
#define X86_VECT_TS 10
/** @brief Segment Not Present */
#define X86_VECT_NP 11
/** @brief Stack-Segment Fault */
#define X86_VECT_SS 12
/** @brief General Protection */
#define X86_VECT_GP 13
/** @brief Page Fault */
#define X86_VECT_PF 14
/* 15 is reserved */
/** @brief x87 FPU Floating Point Error (Math Fault) */
#define X86_VECT_MF 16
/** @brief Alignment Check */
#define X86_VECT_AC 17
/** @brief Machine Check */
#define X86_VECT_MC 18
/** @brief SIMD Floating-Point Exception */
#define X86_VECT_XM 19
/** @brief Virtualization Exception */
#define X86_VECT_VE 20
/** @brief Control Protection Exception */
#define X86_VECT_CP 21
/* 22-31 are reserved, IRQs start at 32 */
#define X86_VECT_IRQ_BASE 32
#ifndef _ASM_SOURCE
#include <gay/cdefs.h>
#include <gay/types.h>
__always_inline void enable_interrupts(void)
{
__asm__ volatile("sti");
}
__always_inline void disable_interrupts(void)
{
__asm__ volatile("cli");
}
/**
* @brief A single entry in the Interrupt Descriptor Table as laid out in hardware.
* Luckily, this is not quite as deranged as the GDT layout.
*/
struct x86_idt_entry {
u16 offset0; /**< @brief ptr to handler, bits 0:15 */
u16 selector; /**< @brief GDT selector, use `X86_KERN_CS` */
u8 _zero; /**< @brief always 0 */
u8 attr;
#define X86_IDT_GATE_TASK32 0x5u
#define X86_IDT_GATE_INTR16 0x6u
#define X86_IDT_GATE_TRAP16 0x7u
#define X86_IDT_GATE_INTR32 0xeu
#define X86_IDT_GATE_TRAP32 0xfu
#define X86_IDT_STORAGE (1u << 4) /* 0 for interrupt/trap, 1 for system gate */
#define X86_IDT_DPL(x) (((x) & 3u) << 5)
#define X86_IDT_PRESENT (1u << 7)
u16 offset1; /**< @brief ptr to handler, bits 16:31 */
} __packed;
/* idt.S */
extern struct x86_idt_entry x86_idt[X86_INTR_COUNT];
/** @brief Disable the Programmable Interrupt Controller. */
void x86_disable_pic(void);
/**
* @brief Set a gate handler in the Interrupt Descriptor Table.
*
* @param vector Vector number in the IDT
* @param handler Address of the handler function
* @param flags Flags for the IDT entry
*/
void x86_set_gate(u8 vector, void (*handler)(void), u8 flags);
/**
* @brief Set a trap gate handler in the Interrupt Descriptor table.
*
* @param vector Vector number in the IDT
* @param isr Address of the interrupt service routine
*/
void x86_set_trap_gate(u8 vector, void (*isr)(void));
/** @brief Set up the IDT and load it into IDTR. */
void x86_setup_interrupts(void);
/** @brief Internal routine performing the actual LIDT instruction. */
extern void x86_load_idt(void);
#endif /* not _ASM_SOURCE */
/*
* This file is part of GayBSD.
* Copyright (c) 2021 fef <owo@fef.moe>.
*
* GayBSD is nonviolent software: you may only use, redistribute, and/or
* modify it under the terms of the Cooperative Nonviolent Public License
* (CNPL) as found in the LICENSE file in the source code root directory
* or at <https://git.pixie.town/thufie/npl-builder>; either version 7
* of the license, or (at your option) any later version.
*
* GayBSD comes with ABSOLUTELY NO WARRANTY, to the extent
* permitted by applicable law. See the CNPL for details.
*/

@ -150,7 +150,6 @@ struct mb2_mmap_entry {
u32 zero;
};
typedef struct mb2_mmap_entry mb2_memory_map_t;
struct mb2_tag {
u32 type;

@ -0,0 +1,86 @@
/* See the end of this file for copyright and license terms. */
#pragma once
#include <gay/types.h>
/** @brief I/O port number for the PIC1 command channel */
#define X86_PORT_PIC1_CMD 0x20
/** @brief I/O port number for the PIC1 data channel */
#define X86_PORT_PIC1_DATA 0x21
/** @brief I/O port number for the keyboard data channel */
#define X86_PORT_KBD_DATA 0x60
/** @brief I/O port number for the keyboard status channel */
#define X86_PORT_KBD_STATUS 0x64
/** @brief I/O port number for the PIC2 command channel */
#define X86_PORT_PIC2_CMD 0xa0
/** @brief I/O port number for the PIC2 data channel */
#define X86_PORT_PIC2_DATA 0xa1
#ifndef _ASM_SOURCE
/**
* @brief Read a byte from the I/O bus.
*
* @param port Port number
* @return The byte that was read
*/
extern u8 x86_inb(u16 port);
/**
* @brief Read a word from the I/O bus.
*
* @param port Port number
* @return The word that was read
*/
extern u16 x86_inw(u16 port);
/**
* @brief Read a longword from the I/O bus.
*
* @param port Port number
* @return The longword that was read
*/
extern u32 x86_inl(u16 port);
/**
* @brief Write a byte to the I/O bus.
*
* @param port Port number
* @param data Byte to send through the port
*/
extern void x86_outb(u16 port, u8 data);
/**
* @brief Write a word to the I/O bus.
*
* @param port Port number
* @param data Word to send through the port
*/
extern void x86_outw(u16 port, u16 data);
/**
* @brief Write a longword to the I/O bus.
*
* @param port Port number
* @param data Longword to send through the port
*/
extern void x86_outl(u16 port, u32 data);
#endif /* not _ASM_SOURCE */
/*
* This file is part of GayBSD.
* Copyright (c) 2021 fef <owo@fef.moe>.
*
* GayBSD is nonviolent software: you may only use, redistribute, and/or
* modify it under the terms of the Cooperative Nonviolent Public License
* (CNPL) as found in the LICENSE file in the source code root directory
* or at <https://git.pixie.town/thufie/npl-builder>; either version 7
* of the license, or (at your option) any later version.
*
* GayBSD comes with ABSOLUTELY NO WARRANTY, to the extent
* permitted by applicable law. See the CNPL for details.
*/

@ -0,0 +1,93 @@
/* See the end of this file for copyright and license terms. */
#pragma once
/**
* @file include/arch/trap.h
* @brief Low level system interrupt handler definitions.
*
* The functions prefixed with an underscore are implemented in assembly and
* are what is actually referenced in the IDT. They call the respective C
* handler (the one without the underscore), and then return from the interrupt.
* Yes i know that there is the thing where compilers automatically prefix C
* symbols with an underscore which potentially leads to a name clash, but clang
* doesn't do that. That is, i hope it doesn't, but i checked and it doesn't
* appear to be the case. Trust me, it's fine.
*/
#include <gay/cdefs.h>
#include <gay/types.h>
extern void _x86_isr_divide_error(void);
__asmlink void x86_isr_divide_error(void);
extern void _x86_isr_debug_exception(void);
__asmlink void x86_isr_debug_exception(void);
extern void _x86_isr_nmi(void);
__asmlink void x86_isr_nmi(void);
extern void _x86_isr_breakpoint(void);
__asmlink void x86_isr_breakpoint(void);
extern void _x86_isr_overflow(void);
__asmlink void x86_isr_overflow(void);
extern void _x86_isr_bound_range_exceeded(void);
__asmlink void x86_isr_bound_range_exceeded(void);
extern void _x86_isr_invalid_opcode(void);
__asmlink void x86_isr_invalid_opcode(void);
extern void _x86_isr_device_not_available(void);
__asmlink void x86_isr_device_not_available(void);
extern void _x86_isr_double_fault(void);
__asmlink void x86_isr_double_fault(u32 error_code);
extern void _x86_isr_invalid_tss(void);
__asmlink void x86_isr_invalid_tss(u32 error_code);
extern void _x86_isr_segment_not_present(void);
__asmlink void x86_isr_segment_not_present(u32 error_code);
extern void _x86_isr_stack_segment_fault(void);
__asmlink void x86_isr_stack_segment_fault(u32 error_code);
extern void _x86_isr_general_protection(void);
__asmlink void x86_isr_general_protection(u32 error_code);
extern void _x86_isr_page_fault(void);
__asmlink void x86_isr_page_fault(u32 error_code);
extern void _x86_isr_x87_fpu_error(void);
__asmlink void x86_isr_x87_fpu_error(void);
extern void _x86_isr_alignment_check(void);
__asmlink void x86_isr_alignment_check(u32 error_code);
extern void _x86_isr_machine_check(void);
__asmlink void x86_isr_machine_check(void);
extern void _x86_isr_simd_floating_point_exception(void);
__asmlink void x86_isr_simd_floating_point_exception(void);
extern void _x86_isr_virtualization_exception(void);
__asmlink void x86_isr_virtualization_exception(void);
extern void _x86_isr_control_protection_exception(void);
__asmlink void x86_isr_control_protection_exception(u32 error_code);
/*
* This file is part of GayBSD.
* Copyright (c) 2021 fef <owo@fef.moe>.
*
* GayBSD is nonviolent software: you may only use, redistribute, and/or
* modify it under the terms of the Cooperative Nonviolent Public License
* (CNPL) as found in the LICENSE file in the source code root directory
* or at <https://git.pixie.town/thufie/npl-builder>; either version 7
* of the license, or (at your option) any later version.
*
* GayBSD comes with ABSOLUTELY NO WARRANTY, to the extent
* permitted by applicable law. See the CNPL for details.
*/

@ -27,7 +27,7 @@ ASM_END(x86_replace_gdt)
.align 4
.word 0 /* padding */
x86_gdt_desc:
.word x86_gdt - x86_gdt_end - 1 /* limit */
.word x86_gdt_end - x86_gdt - 1 /* limit */
.long x86_gdt /* base */
/*

@ -0,0 +1,21 @@
# See the end of this file for copyright and license terms.
target_sources(gay_arch PRIVATE
entry.S
idt.S
interrupt.c
port.S
trap.c
)
# This file is part of GayBSD.
# Copyright (c) 2021 fef <owo@fef.moe>.
#
# GayBSD is nonviolent software: you may only use, redistribute, and/or
# modify it under the terms of the Cooperative Nonviolent Public License
# (CNPL) as found in the LICENSE file in the source code root directory
# or at <https://git.pixie.town/thufie/npl-builder>; either version 7
# of the license, or (at your option) any later version.
#
# GayBSD comes with ABSOLUTELY NO WARRANTY, to the extent
# permitted by applicable law. See the CNPL for details.

@ -0,0 +1,175 @@
/* See the end of this file for copyright and license terms. */
#include <arch/interrupt.h>
#include <asm/common.h>
.text
/*
* low level entry points, this is what gets put into the IDT
*/
ASM_ENTRY(_x86_isr_divide_error)
cld
call x86_isr_divide_error
iret
ASM_END(_x86_isr_divide_error)
ASM_ENTRY(_x86_isr_debug_exception)
cld
call x86_isr_debug_exception
iret
ASM_END(_x86_isr_debug_exception)
ASM_ENTRY(_x86_isr_nmi)
cld
call x86_isr_nmi
iret
ASM_END(_x86_isr_nmi)
ASM_ENTRY(_x86_isr_breakpoint)
cld
call x86_isr_breakpoint
iret
ASM_END(_x86_isr_breakpoint)
ASM_ENTRY(_x86_isr_overflow)
cld
call x86_isr_overflow
iret
ASM_END(_x86_isr_overflow)
ASM_ENTRY(_x86_isr_bound_range_exceeded)
cld
call x86_isr_bound_range_exceeded
iret
ASM_END(_x86_isr_bound_range_exceeded)
ASM_ENTRY(_x86_isr_invalid_opcode)
cld
call x86_isr_invalid_opcode
iret
ASM_END(_x86_isr_invalid_opcode)
ASM_ENTRY(_x86_isr_device_not_available)
cld
call x86_isr_device_not_available
iret
ASM_END(_x86_isr_device_not_available)
ASM_ENTRY(_x86_isr_double_fault)
cld
call x86_isr_double_fault
add $4, %esp
iret
ASM_END(_x86_isr_double_fault)
ASM_ENTRY(_x86_isr_invalid_tss)
cld
call x86_isr_invalid_tss
add $4, %esp
iret
ASM_END(_x86_isr_invalid_tss)
ASM_ENTRY(_x86_isr_segment_not_present)
cld
call x86_isr_segment_not_present
add $4, %esp
iret
ASM_END(_x86_isr_segment_not_present)
ASM_ENTRY(_x86_isr_stack_segment_fault)
cld
call x86_isr_stack_segment_fault
add $4, %esp
iret
ASM_END(_x86_isr_stack_segment_fault)
ASM_ENTRY(_x86_isr_general_protection)
cld
call x86_isr_general_protection
add $4, %esp
iret
ASM_END(_x86_isr_general_protection)
ASM_ENTRY(_x86_isr_page_fault)
cld
call x86_isr_page_fault
add $4, %esp
iret
ASM_END(_x86_isr_page_fault)
ASM_ENTRY(_x86_isr_x87_fpu_error)
cld
call x86_isr_x87_fpu_error
iret
ASM_END(_x86_isr_fpu_error)
ASM_ENTRY(_x86_isr_alignment_check)
cld
call x86_isr_alignment_check
add $4, %esp
iret
ASM_END(_x86_isr_alignment_check)
ASM_ENTRY(_x86_isr_machine_check)
cld
call x86_isr_machine_check
iret
ASM_END(_x86_isr_machine_check)
ASM_ENTRY(_x86_isr_simd_floating_point_exception)
cld
call x86_isr_simd_floating_point_exception
iret
ASM_END(_x86_isr_simd_floating_point_exception)
ASM_ENTRY(_x86_isr_virtualization_exception)
cld
call x86_isr_virtualization_exception
iret
ASM_END(_x86_isr_virtualization_exception)
ASM_ENTRY(_x86_isr_control_protection_exception)
cld
call x86_isr_control_protection_exception
add $4, %esp
iret
ASM_END(_x86_isr_control_protection_exception)
/* trap.c */
.extern x86_isr_divide_error
.extern x86_isr_debug_exception
.extern x86_isr_nmi
.extern x86_isr_breakpoint
.extern x86_isr_overflow
.extern x86_isr_bound_range_exceeded
.extern x86_isr_invalid_opcode
.extern x86_isr_device_not_available
.extern x86_isr_double_fault
.extern x86_isr_invalid_tss
.extern x86_isr_segment_not_present
.extern x86_isr_stack_segment_fault
.extern x86_isr_general_protection
.extern x86_isr_page_fault
.extern x86_isr_x87_fpu_error
.extern x86_isr_alignment_check
.extern x86_isr_machine_check
.extern x86_isr_simd_floating_point_exception
.extern x86_isr_virtualization_exception
.extern x86_isr_control_protection_exception
/*
* This file is part of GayBSD.
* Copyright (c) 2021 fef <owo@fef.moe>.
*
* GayBSD is nonviolent software: you may only use, redistribute, and/or
* modify it under the terms of the Cooperative Nonviolent Public License
* (CNPL) as found in the LICENSE file in the source code root directory
* or at <https://git.pixie.town/thufie/npl-builder>; either version 7
* of the license, or (at your option) any later version.
*
* GayBSD comes with ABSOLUTELY NO WARRANTY, to the extent
* permitted by applicable law. See the CNPL for details.
*/

@ -0,0 +1,44 @@
/* See the end of this file for copyright and license terms. */
#include <arch/interrupt.h>
#include <asm/common.h>
.text
/* void x86_load_idt(void) */
ASM_ENTRY(x86_load_idt)
lidt x86_idt_desc
ret
ASM_END(x86_load_idt)
.data
.align 4
.word 0 /* padding */
x86_idt_desc:
.word x86_idt_end - x86_idt - 1 /* limit (size in bytes - 1) */
.long x86_idt /* base */
.size x86_idt_desc, . - x86_idt_desc
.align 16
.global x86_idt
x86_idt:
.fill X86_INTR_COUNT, 8, 0 /* empty idt, initialized dynamically */
x86_idt_end:
.size x86_idt, . - x86_idt
/*
* This file is part of GayBSD.
* Copyright (c) 2021 fef <owo@fef.moe>.
*
* GayBSD is nonviolent software: you may only use, redistribute, and/or
* modify it under the terms of the Cooperative Nonviolent Public License
* (CNPL) as found in the LICENSE file in the source code root directory
* or at <https://git.pixie.town/thufie/npl-builder>; either version 7
* of the license, or (at your option) any later version.
*
* GayBSD comes with ABSOLUTELY NO WARRANTY, to the extent
* permitted by applicable law. See the CNPL for details.
*/

@ -0,0 +1,77 @@
/* See the end of this file for copyright and license terms. */
#include <arch/interrupt.h>
#include <arch/port.h>
#include <arch/segment.h>
#include <arch/trap.h>
#include <gay/kprintf.h>
#include <gay/types.h>
void x86_setup_interrupts(void)
{
x86_disable_pic();
x86_set_trap_gate(X86_VECT_DE, _x86_isr_divide_error);
x86_set_trap_gate(X86_VECT_DB, _x86_isr_debug_exception);
x86_set_trap_gate(X86_VECT_NMI, _x86_isr_nmi);
x86_set_trap_gate(X86_VECT_BP, _x86_isr_breakpoint);
x86_set_trap_gate(X86_VECT_OF, _x86_isr_overflow);
x86_set_trap_gate(X86_VECT_BR, _x86_isr_bound_range_exceeded);
x86_set_trap_gate(X86_VECT_UD, _x86_isr_invalid_opcode);
x86_set_trap_gate(X86_VECT_NM, _x86_isr_device_not_available);
x86_set_trap_gate(X86_VECT_DF, _x86_isr_double_fault);
x86_set_trap_gate(X86_VECT_TS, _x86_isr_invalid_tss);
x86_set_trap_gate(X86_VECT_NP, _x86_isr_segment_not_present);
x86_set_trap_gate(X86_VECT_SS, _x86_isr_stack_segment_fault);
x86_set_trap_gate(X86_VECT_GP, _x86_isr_general_protection);
x86_set_trap_gate(X86_VECT_PF, _x86_isr_page_fault);
x86_set_trap_gate(X86_VECT_MF, _x86_isr_x87_fpu_error);
x86_set_trap_gate(X86_VECT_AC, _x86_isr_alignment_check);
x86_set_trap_gate(X86_VECT_MC, _x86_isr_machine_check);
x86_set_trap_gate(X86_VECT_XM, _x86_isr_simd_floating_point_exception);
x86_set_trap_gate(X86_VECT_VE, _x86_isr_virtualization_exception);
x86_set_trap_gate(X86_VECT_CP, _x86_isr_control_protection_exception);
x86_load_idt();
enable_interrupts();
}
void x86_set_gate(u8 vector, void (*handler)(void), u8 flags)
{
struct x86_idt_entry *entry = &x86_idt[vector];
entry->offset0 = (uintptr_t)handler & 0xffff;
entry->offset1 = ((uintptr_t)handler >> 16) & 0xffff;
entry->selector = X86_KERN_CS;
entry->_zero = 0;
entry->attr = flags;
}
void x86_set_trap_gate(u8 vector, void (*isr)(void))
{
u8 flags = X86_IDT_PRESENT | X86_IDT_GATE_TRAP32 | X86_IDT_DPL(0);
if (vector < X86_VECT_IRQ_BASE)
x86_set_gate(vector, isr, flags);
else
kprintf("Tried to assign non-trap vector %d to a trap gate\n", vector);
}
void x86_disable_pic(void)
{
x86_outb(X86_PORT_PIC2_DATA, 0xff);
x86_outb(X86_PORT_PIC1_DATA, 0xff);
}
/*
* This file is part of GayBSD.
* Copyright (c) 2021 fef <owo@fef.moe>.
*
* GayBSD is nonviolent software: you may only use, redistribute, and/or
* modify it under the terms of the Cooperative Nonviolent Public License
* (CNPL) as found in the LICENSE file in the source code root directory
* or at <https://git.pixie.town/thufie/npl-builder>; either version 7
* of the license, or (at your option) any later version.
*
* GayBSD comes with ABSOLUTELY NO WARRANTY, to the extent
* permitted by applicable law. See the CNPL for details.
*/

@ -0,0 +1,67 @@
/* See the end of this file for copyright and license terms. */
#include <asm/common.h>
.text
/* u8 x86_inb(u16 port); */
ASM_ENTRY(x86_inb)
mov 4(%esp), %edx
xor %eax, %eax
inb %dx, %al
ret
ASM_END(x86_inb)
/* u16 x86_inw(u16 port); */
ASM_ENTRY(x86_inw)
mov 4(%esp), %edx
xor %eax, %eax
inw %dx, %ax
ret
ASM_END(x86_inw)
/* u32 x86_inl(u16 port); */
ASM_ENTRY(x86_inl)
mov 4(%esp), %edx
xor %eax, %eax
inl %dx, %eax
ret
ASM_END(x86_inl)
/* void x86_outb(u16 port, u8 data); */
ASM_ENTRY(x86_outb)
mov 4(%esp), %edx
mov 8(%esp), %eax
outb %al, %dx
ret
ASM_END(x86_outb)
/* void x86_outw(u16 port, u16 data); */
ASM_ENTRY(x86_outw)
mov 4(%esp), %edx
mov 8(%esp), %eax
outw %ax, %dx
ret
ASM_END(x86_outw)
/* void x86_outl(u16 port, u32 data); */
ASM_ENTRY(x86_outl)
mov 4(%esp), %edx
mov 8(%esp), %eax
outl %eax, %dx
ret
ASM_END(x86_outl)
/*
* This file is part of GayBSD.
* Copyright (c) 2021 fef <owo@fef.moe>.
*
* GayBSD is nonviolent software: you may only use, redistribute, and/or
* modify it under the terms of the Cooperative Nonviolent Public License
* (CNPL) as found in the LICENSE file in the source code root directory
* or at <https://git.pixie.town/thufie/npl-builder>; either version 7
* of the license, or (at your option) any later version.
*
* GayBSD comes with ABSOLUTELY NO WARRANTY, to the extent
* permitted by applicable law. See the CNPL for details.
*/

@ -0,0 +1,146 @@
/* See the end of this file for copyright and license terms. */
#include <arch/trap.h>
#include <gay/kprintf.h>
/*
* NOTE: The error code is cast to a pointer for the kprintf() calls, this is
* just for looks because i haven't implemented the %x format sequence yet so
* this is the only way to print hex numbers.
*/
void x86_isr_divide_error(void)
{
kprintf("Divide Error\n");
while (1);
}
void x86_isr_debug_exception(void)
{
kprintf("Debug Exception\n");
while (1);
}
void x86_isr_nmi(void)
{
kprintf("Nonmaskable Interrupt\n");
while (1);
}
void x86_isr_breakpoint(void)
{
kprintf("Breakpoint\n");
while (1);
}
void x86_isr_overflow(void)
{
kprintf("Overflow\n");
while (1);
}
void x86_isr_bound_range_exceeded(void)
{
kprintf("Bound Range Exceeded\n");
while (1);
}
void x86_isr_invalid_opcode(void)
{
kprintf("Invalid Opcode\n");
while (1);
}
void x86_isr_device_not_available(void)
{
kprintf("Device Not Available\n");
while (1);
}
void x86_isr_double_fault(u32 error_code)
{
kprintf("Double Fault (error = %p)\n", (void *)error_code);
while (1);
}
void x86_isr_invalid_tss(u32 error_code)
{
kprintf("Invalid TSS (error = %p)\n", (void *)error_code);
while (1);
}
void x86_isr_segment_not_present(u32 error_code)
{
kprintf("Segment Not Present (error = %p)\n", (void *)error_code);
while (1);
}
void x86_isr_stack_segment_fault(u32 error_code)
{
kprintf("Stack Segment Fault (error = %p)\n", (void *)error_code);
while (1);
}
void x86_isr_general_protection(u32 error_code)
{
kprintf("General Protection Fault (external = %d, table = %d, index = %d)\n",
error_code & 1, (error_code >> 1) & 3, (error_code >> 3));
while (1);
}
void x86_isr_page_fault(u32 error_code)
{
kprintf("Page Fault (error = %p)\n", (void *)error_code);
while (1);
}
void x86_isr_x87_fpu_error(void)
{
kprintf("x87 FPU Error\n");
while (1);
}
void x86_isr_alignment_check(u32 error_code)
{
kprintf("Alignment Check (error = %p)\n", (void *)error_code);
while (1);
}
void x86_isr_machine_check(void)
{
kprintf("Machine Check\n");
while (1);
}
void x86_isr_simd_floating_point_exception(void)
{
kprintf("SIMD Floating Point Exception\n");
while (1);
}
void x86_isr_virtualization_exception(void)
{
kprintf("Virtualization Exception\n");
while (1);
}
void x86_isr_control_protection_exception(u32 error_code)
{
kprintf("Control Protection Exception (error = %p)\n", (void *)error_code);
while (1);
}
/*
* This file is part of GayBSD.
* Copyright (c) 2021 fef <owo@fef.moe>.
*
* GayBSD is nonviolent software: you may only use, redistribute, and/or
* modify it under the terms of the Cooperative Nonviolent Public License
* (CNPL) as found in the LICENSE file in the source code root directory
* or at <https://git.pixie.town/thufie/npl-builder>; either version 7
* of the license, or (at your option) any later version.
*
* GayBSD comes with ABSOLUTELY NO WARRANTY, to the extent
* permitted by applicable law. See the CNPL for details.
*/

@ -14,10 +14,21 @@
#define __aligned(bytes) __attribute__(( aligned(bytes) ))
#define __always_inline inline __attribute__(( always_inline ))
#define __packed __attribute__(( packed ))
#define __section(name) __attribute__(( section(#name) ))
#define __used __attribute__(( used ))
#ifdef __cplusplus__
#define __asmlink __used extern "C"
#else
/* this is mainly for IDEs w/out full assembly support (looking at you, CLion) */
#define __asmlink __used
#endif
#ifndef NULL
#define NULL ((void *)0)
#endif

Loading…
Cancel
Save