mirror of https://github.com/tailix/kernel.git
Compare commits
9 Commits
8a9a586b51
...
b2ef7c4073
Author | SHA1 | Date |
---|---|---|
Alex Kotov | b2ef7c4073 | |
Alex Kotov | e46588a13e | |
Alex Kotov | 08e17da327 | |
Alex Kotov | a2163e6493 | |
Alex Kotov | 921d7a2ae7 | |
Alex Kotov | 9e55308d5f | |
Alex Kotov | d625623625 | |
Alex Kotov | dd270c997b | |
Alex Kotov | c65fc174ac |
10
README.md
10
README.md
|
@ -3,5 +3,15 @@ Tailix kernel
|
|||
|
||||
My OS kernel attempt =)
|
||||
|
||||
Links
|
||||
-----
|
||||
|
||||
### Paging
|
||||
|
||||
* https://stackoverflow.com/a/6224824
|
||||
* https://littleosbook.github.io/#paging-and-the-kernel
|
||||
|
||||
### Interrupts
|
||||
|
||||
* https://www.kernel.org/doc/Documentation/x86/kernel-stacks
|
||||
* https://lwn.net/Articles/484932/
|
||||
|
|
13
src/Makefile
13
src/Makefile
|
@ -21,8 +21,8 @@ CFLAGS = \
|
|||
-I$(DRIVERS_PREFIX)/include
|
||||
|
||||
CPPFLAGS = \
|
||||
-DKERNAUX_ENABLE_ASSERT \
|
||||
-DKERNAUX_ENABLE_GUARD
|
||||
-DKERNAUX_DEBUG \
|
||||
-DKERNAUX_BITFIELDS
|
||||
|
||||
# Architecture-dependent
|
||||
OBJS = start.s.o
|
||||
|
@ -33,15 +33,8 @@ OBJS += paging.c.o
|
|||
# Architecture-independent
|
||||
OBJS += info.c.o
|
||||
|
||||
# Built-in drivers
|
||||
OBJS += timer.c.o
|
||||
|
||||
OBJS += protected.c.o
|
||||
|
||||
OBJS += interrupts/main.asm.cpp.o
|
||||
OBJS += interrupts/exception.c.o
|
||||
OBJS += interrupts/hwint.c.o
|
||||
OBJS += interrupts/syscall.c.o
|
||||
OBJS += interrupts.c.o interrupts.asm.cpp.o
|
||||
|
||||
all: $(KERNEL)
|
||||
|
||||
|
|
|
@ -3,8 +3,6 @@
|
|||
|
||||
#define MEM_UPPER_BASE ((unsigned long)(1 * 1024 * 1024)) // 1 MB
|
||||
|
||||
#define IDT_SIZE 256 // maximal size
|
||||
|
||||
#define GDT_NULL_INDEX 0
|
||||
#define GDT_KERNEL_CS_INDEX 1
|
||||
#define GDT_KERNEL_DS_INDEX 2
|
||||
|
|
|
@ -0,0 +1,98 @@
|
|||
#include "config.h"
|
||||
|
||||
[EXTERN interrupts_handler]
|
||||
|
||||
%macro NOERRCODE 1
|
||||
[GLOBAL interrupts_cb_%1]
|
||||
interrupts_cb_%1:
|
||||
push dword 0
|
||||
push dword %1
|
||||
jmp common_part
|
||||
%endmacro
|
||||
|
||||
%macro ERRCODE 1
|
||||
[GLOBAL interrupts_cb_%1]
|
||||
interrupts_cb_%1:
|
||||
push dword %1
|
||||
jmp common_part
|
||||
%endmacro
|
||||
|
||||
common_part:
|
||||
pushad
|
||||
|
||||
mov ax, ds ; Lower 16-bits of eax = ds.
|
||||
push dword eax ; save the data segment descriptor
|
||||
|
||||
mov ax, GDT_KERNEL_DS_SELECTOR
|
||||
mov ds, ax
|
||||
mov es, ax
|
||||
mov fs, ax
|
||||
mov gs, ax
|
||||
|
||||
call interrupts_handler
|
||||
|
||||
pop dword eax ; reload the original data segment descriptor
|
||||
mov ds, ax
|
||||
mov es, ax
|
||||
mov fs, ax
|
||||
mov gs, ax
|
||||
|
||||
popad
|
||||
|
||||
add esp, 8 ; Cleans up the pushed error code and pushed ISR number
|
||||
iret ; pops 5 things at once: CS, EIP, EFLAGS, SS, and ESP
|
||||
|
||||
; Protected mode exteptions
|
||||
|
||||
NOERRCODE 0x00 ; #DE - Divide Error Exception
|
||||
NOERRCODE 0x01 ; #DB - Debug Exception
|
||||
NOERRCODE 0x02 ; NMI - Non-maskable interrupt
|
||||
NOERRCODE 0x03 ; #BP - Breakpoint Exception
|
||||
NOERRCODE 0x04 ; #OF - Overflow Exception
|
||||
NOERRCODE 0x05 ; #BR - BOUND Range Exceeded Exception
|
||||
NOERRCODE 0x06 ; #UD - Invalid Opcode Exception
|
||||
NOERRCODE 0x07 ; #NM - Device Not Available Exception
|
||||
ERRCODE 0x08 ; #DF - Double Fault Exception
|
||||
NOERRCODE 0x09 ; Reserved - Coprocessor Segment Overrun
|
||||
ERRCODE 0x0a ; #TS - Invalid TSS Exception
|
||||
ERRCODE 0x0b ; #NP - Segment Not Present
|
||||
ERRCODE 0x0c ; #SS - Stack Fault Exception
|
||||
ERRCODE 0x0d ; #GP - General Protection Exception
|
||||
ERRCODE 0x0e ; #PF - Page-Fault Exception
|
||||
NOERRCODE 0x0f ; Reserved
|
||||
NOERRCODE 0x10 ; #MF - x87 FPU Floating-Point Error
|
||||
ERRCODE 0x11 ; #AC - Alignment Check Exception
|
||||
NOERRCODE 0x12 ; #MC - Machine-Check Exception
|
||||
NOERRCODE 0x13 ; #XF - SIMD Floating-Point Exception
|
||||
NOERRCODE 0x14 ; Reserved
|
||||
NOERRCODE 0x15 ; Reserved
|
||||
NOERRCODE 0x16 ; Reserved
|
||||
NOERRCODE 0x17 ; Reserved
|
||||
NOERRCODE 0x18 ; Reserved
|
||||
NOERRCODE 0x19 ; Reserved
|
||||
NOERRCODE 0x1a ; Reserved
|
||||
NOERRCODE 0x1b ; Reserved
|
||||
NOERRCODE 0x1c ; Reserved
|
||||
NOERRCODE 0x1d ; Reserved
|
||||
NOERRCODE 0x1e ; Reserved
|
||||
NOERRCODE 0x1f ; Reserved
|
||||
|
||||
; Hardware IRQs
|
||||
|
||||
NOERRCODE 0x20 ; Programmable Interval Timer
|
||||
NOERRCODE 0x21 ; Keyboard
|
||||
NOERRCODE 0x22 ; Slave PIC
|
||||
NOERRCODE 0x23 ; COM 2/4
|
||||
NOERRCODE 0x24 ; COM 1/3
|
||||
NOERRCODE 0x25 ; LPT 2
|
||||
NOERRCODE 0x26 ; Floppy Drive Controller
|
||||
NOERRCODE 0x27 ; LPT 1
|
||||
|
||||
NOERRCODE 0x28 ; Real Time Clock
|
||||
NOERRCODE 0x29 ; Master PIC
|
||||
NOERRCODE 0x2a ; Reserved
|
||||
NOERRCODE 0x2b ; Reserved
|
||||
NOERRCODE 0x2c ; Reserved
|
||||
NOERRCODE 0x2d ; Coprocessor exception
|
||||
NOERRCODE 0x2e ; Hard Drive Controller
|
||||
NOERRCODE 0x2f ; Reserved
|
|
@ -0,0 +1,95 @@
|
|||
#include <kernaux/arch/i386.h>
|
||||
#include <kernaux/asm/i386.h>
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#define IDT_SIZE 256
|
||||
|
||||
static struct KernAux_Arch_I386_DTR idt_pointer;
|
||||
static struct KernAux_Arch_I386_IDTE idt[IDT_SIZE];
|
||||
|
||||
void interrupts_init()
|
||||
{
|
||||
memset(&idt_pointer, 0, sizeof(idt_pointer));
|
||||
memset(&idt, 0, sizeof(idt));
|
||||
}
|
||||
|
||||
void interrupts_load()
|
||||
{
|
||||
idt_pointer.size = sizeof(struct KernAux_Arch_I386_IDTE) * IDT_SIZE - 1;
|
||||
idt_pointer.offset = (uint32_t)&idt;
|
||||
kernaux_asm_i386_flush_idt((uint32_t)&idt_pointer);
|
||||
}
|
||||
|
||||
void interrupts_handler() {}
|
||||
|
||||
#define init_intr(num, dpl) do { \
|
||||
void interrupts_cb_##num(); \
|
||||
KernAux_Arch_I386_IDTE_init_intr( \
|
||||
&idt[num], \
|
||||
(uint32_t)interrupts_cb_##num, \
|
||||
kernel_cs_selector, \
|
||||
dpl \
|
||||
); \
|
||||
} while (0)
|
||||
|
||||
void interrupts_setup(const uint16_t kernel_cs_selector)
|
||||
{
|
||||
memset(idt, 0, sizeof(idt));
|
||||
|
||||
// Protected mode exteptions
|
||||
|
||||
init_intr(0x00, 0);
|
||||
init_intr(0x01, 0);
|
||||
init_intr(0x02, 0);
|
||||
init_intr(0x03, 0);
|
||||
init_intr(0x04, 0);
|
||||
init_intr(0x05, 0);
|
||||
init_intr(0x06, 0);
|
||||
init_intr(0x07, 0);
|
||||
init_intr(0x08, 0);
|
||||
init_intr(0x09, 0);
|
||||
init_intr(0x0a, 0);
|
||||
init_intr(0x0b, 0);
|
||||
init_intr(0x0c, 0);
|
||||
init_intr(0x0d, 0);
|
||||
init_intr(0x0e, 0);
|
||||
init_intr(0x0f, 0);
|
||||
init_intr(0x10, 0);
|
||||
init_intr(0x11, 0);
|
||||
init_intr(0x12, 0);
|
||||
init_intr(0x13, 0);
|
||||
init_intr(0x14, 0);
|
||||
init_intr(0x15, 0);
|
||||
init_intr(0x16, 0);
|
||||
init_intr(0x17, 0);
|
||||
init_intr(0x18, 0);
|
||||
init_intr(0x19, 0);
|
||||
init_intr(0x1a, 0);
|
||||
init_intr(0x1b, 0);
|
||||
init_intr(0x1c, 0);
|
||||
init_intr(0x1d, 0);
|
||||
init_intr(0x1e, 0);
|
||||
init_intr(0x1f, 0);
|
||||
|
||||
// Hardware IRQs
|
||||
|
||||
init_intr(0x20, 0);
|
||||
init_intr(0x21, 0);
|
||||
init_intr(0x22, 0);
|
||||
init_intr(0x23, 0);
|
||||
init_intr(0x24, 0);
|
||||
init_intr(0x25, 0);
|
||||
init_intr(0x26, 0);
|
||||
init_intr(0x27, 0);
|
||||
|
||||
init_intr(0x28, 0);
|
||||
init_intr(0x29, 0);
|
||||
init_intr(0x2a, 0);
|
||||
init_intr(0x2b, 0);
|
||||
init_intr(0x2c, 0);
|
||||
init_intr(0x2d, 0);
|
||||
init_intr(0x2e, 0);
|
||||
init_intr(0x2f, 0);
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
#ifndef KERNEL_INCLUDED_INTERRUPTS
|
||||
#define KERNEL_INCLUDED_INTERRUPTS
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
void interrupts_init();
|
||||
void interrupts_load();
|
||||
void interrupts_setup(uint16_t kernel_cs_selector);
|
||||
|
||||
#endif
|
|
@ -1,16 +0,0 @@
|
|||
#ifndef KERNEL_INCLUDED_INTERRUPTS_CONFIG
|
||||
#define KERNEL_INCLUDED_INTERRUPTS_CONFIG 1
|
||||
|
||||
#define INT_EXCEPTION_COUNT 32
|
||||
#define INT_HWINT_COUNT 16
|
||||
#define INT_TOTAL_COUNT (INT_EXCEPTION_COUNT + INT_HWINT_COUNT)
|
||||
|
||||
#define INT_EXCEPTION_FIRST 0
|
||||
#define INT_EXCEPTION_LAST (INT_EXCEPTION_FIRST + INT_EXCEPTION_COUNT - 1)
|
||||
|
||||
#define INT_HWINT_FIRST (INT_EXCEPTION_LAST + 1)
|
||||
#define INT_HWINT_LAST (INT_HWINT_FIRST + INT_HWINT_COUNT - 1)
|
||||
|
||||
#define INT_SYSCALL 0x80
|
||||
|
||||
#endif
|
|
@ -1,51 +0,0 @@
|
|||
#include "main.h"
|
||||
#include "../panic.h"
|
||||
|
||||
#include <drivers/console.h>
|
||||
|
||||
static const char *const messages[] = {
|
||||
"0 #DE - Divide Error Exception",
|
||||
"1 #DB - Debug Exception",
|
||||
"2 NMI - Non-maskable interrupt",
|
||||
"3 #BP - Breakpoint Exception",
|
||||
"4 #OF - Overflow Exception",
|
||||
"5 #BR - BOUND Range Exceeded Exception",
|
||||
"6 #UD - Invalid Opcode Exception",
|
||||
"7 #NM - Device Not Available Exception",
|
||||
"8 #DF - Double Fault Exception",
|
||||
"9 Reserved - Coprocessor Segment Overrun",
|
||||
"10 #TS - Invalid TSS Exception",
|
||||
"11 #NP - Segment Not Present",
|
||||
"12 #SS - Stack Fault Exception",
|
||||
"13 #GP - General Protection Exception",
|
||||
"14 #PF - Page-Fault Exception",
|
||||
"15 Reserved",
|
||||
"16 #MF - x87 FPU Floating-Point Error",
|
||||
"17 #AC - Alignment Check Exception",
|
||||
"18 #MC - Machine-Check Exception",
|
||||
"19 #XF - SIMD Floating-Point Exception",
|
||||
"20 Reserved",
|
||||
"21 Reserved",
|
||||
"22 Reserved",
|
||||
"23 Reserved",
|
||||
"24 Reserved",
|
||||
"25 Reserved",
|
||||
"26 Reserved",
|
||||
"27 Reserved",
|
||||
"28 Reserved",
|
||||
"29 Reserved",
|
||||
"30 Reserved",
|
||||
"31 Reserved"
|
||||
};
|
||||
|
||||
void exception_handler(struct IsrRegisters regs)
|
||||
{
|
||||
if (regs.int_no > INT_EXCEPTION_LAST) return;
|
||||
|
||||
drivers_console_printf(
|
||||
"[FAIL] exception: Unhandled protected-mode exception: %s\n",
|
||||
messages[regs.int_no]
|
||||
);
|
||||
|
||||
panic("Can not continue.");
|
||||
}
|
|
@ -1,43 +0,0 @@
|
|||
#include "main.h"
|
||||
|
||||
#include <drivers/console.h>
|
||||
#include <drivers/intel_8259_pic.h>
|
||||
|
||||
static hwint_handler_t handlers[INT_HWINT_COUNT] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
|
||||
|
||||
void hwint_handler(struct IsrRegisters regs)
|
||||
{
|
||||
if (regs.int_no >= INT_HWINT_COUNT) return;
|
||||
|
||||
const unsigned char hwint_no = regs.int_no - INT_HWINT_FIRST;
|
||||
|
||||
const hwint_handler_t handler = handlers[hwint_no];
|
||||
|
||||
if (!handler) {
|
||||
drivers_console_printf("[WARN] hwint: Unhandled hardware interrupt: %u\n", hwint_no);
|
||||
return;
|
||||
}
|
||||
|
||||
handler();
|
||||
drivers_intel_8259_pic_eoi(regs.int_no);
|
||||
}
|
||||
|
||||
void hwint_register_handler(unsigned int int_no, hwint_handler_t handler)
|
||||
{
|
||||
if (int_no >= INT_HWINT_COUNT) {
|
||||
return;
|
||||
}
|
||||
|
||||
handlers[int_no] = handler;
|
||||
drivers_intel_8259_pic_enable(int_no);
|
||||
}
|
||||
|
||||
void hwint_unregister_handler(unsigned int int_no)
|
||||
{
|
||||
if (int_no >= INT_HWINT_COUNT) {
|
||||
return;
|
||||
}
|
||||
|
||||
drivers_intel_8259_pic_disable(int_no);
|
||||
handlers[int_no] = 0;
|
||||
}
|
|
@ -1,111 +0,0 @@
|
|||
#include "../config.h"
|
||||
#include "config.h"
|
||||
|
||||
%macro INTERRUPT_NOERRCODE 2
|
||||
[GLOBAL interrupt_%2]
|
||||
interrupt_%2:
|
||||
cli
|
||||
push dword 0
|
||||
push dword %2
|
||||
jmp %1_wrapper
|
||||
%endmacro
|
||||
|
||||
%macro INTERRUPT_ERRCODE 2
|
||||
[GLOBAL interrupt_%2]
|
||||
interrupt_%2:
|
||||
cli
|
||||
push dword %2
|
||||
jmp %1_wrapper
|
||||
%endmacro
|
||||
|
||||
%macro INTERRUPT_COMMON 1
|
||||
[EXTERN %1_handler]
|
||||
%1_wrapper:
|
||||
pushad
|
||||
|
||||
mov ax, ds ; Lower 16-bits of eax = ds.
|
||||
push dword eax ; save the data segment descriptor
|
||||
|
||||
mov ax, GDT_KERNEL_DS_SELECTOR
|
||||
mov ds, ax
|
||||
mov es, ax
|
||||
mov fs, ax
|
||||
mov gs, ax
|
||||
|
||||
call %1_handler
|
||||
|
||||
pop dword eax ; reload the original data segment descriptor
|
||||
mov ds, ax
|
||||
mov es, ax
|
||||
mov fs, ax
|
||||
mov gs, ax
|
||||
|
||||
popad
|
||||
|
||||
add esp, 8 ; Cleans up the pushed error code and pushed ISR number
|
||||
sti
|
||||
iret ; pops 5 things at once: CS, EIP, EFLAGS, SS, and ESP
|
||||
%endmacro
|
||||
|
||||
INTERRUPT_COMMON exception
|
||||
INTERRUPT_COMMON hwint
|
||||
INTERRUPT_COMMON syscall
|
||||
|
||||
; Protected mode exteptions
|
||||
|
||||
INTERRUPT_NOERRCODE exception, 0 ; #DE - Divide Error Exception
|
||||
INTERRUPT_NOERRCODE exception, 1 ; #DB - Debug Exception
|
||||
INTERRUPT_NOERRCODE exception, 2 ; NMI - Non-maskable interrupt
|
||||
INTERRUPT_NOERRCODE exception, 3 ; #BP - Breakpoint Exception
|
||||
INTERRUPT_NOERRCODE exception, 4 ; #OF - Overflow Exception
|
||||
INTERRUPT_NOERRCODE exception, 5 ; #BR - BOUND Range Exceeded Exception
|
||||
INTERRUPT_NOERRCODE exception, 6 ; #UD - Invalid Opcode Exception
|
||||
INTERRUPT_NOERRCODE exception, 7 ; #NM - Device Not Available Exception
|
||||
INTERRUPT_ERRCODE exception, 8 ; #DF - Double Fault Exception
|
||||
INTERRUPT_NOERRCODE exception, 9 ; Reserved - Coprocessor Segment Overrun
|
||||
INTERRUPT_ERRCODE exception, 10 ; #TS - Invalid TSS Exception
|
||||
INTERRUPT_ERRCODE exception, 11 ; #NP - Segment Not Present
|
||||
INTERRUPT_ERRCODE exception, 12 ; #SS - Stack Fault Exception
|
||||
INTERRUPT_ERRCODE exception, 13 ; #GP - General Protection Exception
|
||||
INTERRUPT_ERRCODE exception, 14 ; #PF - Page-Fault Exception
|
||||
INTERRUPT_NOERRCODE exception, 15 ; Reserved
|
||||
INTERRUPT_NOERRCODE exception, 16 ; #MF - x87 FPU Floating-Point Error
|
||||
INTERRUPT_ERRCODE exception, 17 ; #AC - Alignment Check Exception
|
||||
INTERRUPT_NOERRCODE exception, 18 ; #MC - Machine-Check Exception
|
||||
INTERRUPT_NOERRCODE exception, 19 ; #XF - SIMD Floating-Point Exception
|
||||
INTERRUPT_NOERRCODE exception, 20 ; Reserved
|
||||
INTERRUPT_NOERRCODE exception, 21 ; Reserved
|
||||
INTERRUPT_NOERRCODE exception, 22 ; Reserved
|
||||
INTERRUPT_NOERRCODE exception, 23 ; Reserved
|
||||
INTERRUPT_NOERRCODE exception, 24 ; Reserved
|
||||
INTERRUPT_NOERRCODE exception, 25 ; Reserved
|
||||
INTERRUPT_NOERRCODE exception, 26 ; Reserved
|
||||
INTERRUPT_NOERRCODE exception, 27 ; Reserved
|
||||
INTERRUPT_NOERRCODE exception, 28 ; Reserved
|
||||
INTERRUPT_NOERRCODE exception, 29 ; Reserved
|
||||
INTERRUPT_NOERRCODE exception, 30 ; Reserved
|
||||
INTERRUPT_NOERRCODE exception, 31 ; Reserved
|
||||
|
||||
; Hardware IRQs
|
||||
|
||||
INTERRUPT_NOERRCODE hwint, 32 ; Programmable Interval Timer
|
||||
INTERRUPT_NOERRCODE hwint, 33 ; Keyboard
|
||||
INTERRUPT_NOERRCODE hwint, 34 ; Slave PIC
|
||||
INTERRUPT_NOERRCODE hwint, 35 ; COM 2/4
|
||||
INTERRUPT_NOERRCODE hwint, 36 ; COM 1/3
|
||||
INTERRUPT_NOERRCODE hwint, 37 ; LPT 2
|
||||
INTERRUPT_NOERRCODE hwint, 38 ; Floppy Drive Controller
|
||||
INTERRUPT_NOERRCODE hwint, 39 ; LPT 1
|
||||
|
||||
INTERRUPT_NOERRCODE hwint, 40 ; Real Time Clock
|
||||
INTERRUPT_NOERRCODE hwint, 41 ; Master PIC
|
||||
INTERRUPT_NOERRCODE hwint, 42 ; Reserved
|
||||
INTERRUPT_NOERRCODE hwint, 43 ; Reserved
|
||||
INTERRUPT_NOERRCODE hwint, 44 ; Reserved
|
||||
INTERRUPT_NOERRCODE hwint, 45 ; Coprocessor exception
|
||||
INTERRUPT_NOERRCODE hwint, 46 ; Hard Drive Controller
|
||||
INTERRUPT_NOERRCODE hwint, 47 ; Reserved
|
||||
|
||||
; Syscalls
|
||||
|
||||
INTERRUPT_NOERRCODE syscall, INT_SYSCALL
|
|
@ -1,89 +0,0 @@
|
|||
#ifndef KERNEL_INCLUDED_INTERRUPTS_MAIN
|
||||
#define KERNEL_INCLUDED_INTERRUPTS_MAIN 1
|
||||
|
||||
#include "config.h"
|
||||
|
||||
struct IsrRegisters {
|
||||
unsigned int ds; // Data segment selector
|
||||
unsigned int edi, esi, ebp, esp, ebx, edx, ecx, eax; // Pushed by pusha.
|
||||
unsigned int int_no, err_code; // Interrupt number and error code (if applicable)
|
||||
unsigned int ip, cs, flags, sp, ss; // Pushed by the processor automatically.
|
||||
};
|
||||
|
||||
// Protected mode exteptions
|
||||
void interrupt_0();
|
||||
void interrupt_1();
|
||||
void interrupt_2();
|
||||
void interrupt_3();
|
||||
void interrupt_4();
|
||||
void interrupt_5();
|
||||
void interrupt_6();
|
||||
void interrupt_7();
|
||||
void interrupt_8();
|
||||
void interrupt_9();
|
||||
void interrupt_10();
|
||||
void interrupt_11();
|
||||
void interrupt_12();
|
||||
void interrupt_13();
|
||||
void interrupt_14();
|
||||
void interrupt_15();
|
||||
void interrupt_16();
|
||||
void interrupt_17();
|
||||
void interrupt_18();
|
||||
void interrupt_19();
|
||||
void interrupt_20();
|
||||
void interrupt_21();
|
||||
void interrupt_22();
|
||||
void interrupt_23();
|
||||
void interrupt_24();
|
||||
void interrupt_25();
|
||||
void interrupt_26();
|
||||
void interrupt_27();
|
||||
void interrupt_28();
|
||||
void interrupt_29();
|
||||
void interrupt_30();
|
||||
void interrupt_31();
|
||||
|
||||
// Hardware IRQs
|
||||
void interrupt_32();
|
||||
void interrupt_33();
|
||||
void interrupt_34();
|
||||
void interrupt_35();
|
||||
void interrupt_36();
|
||||
void interrupt_37();
|
||||
void interrupt_38();
|
||||
void interrupt_39();
|
||||
void interrupt_40();
|
||||
void interrupt_41();
|
||||
void interrupt_42();
|
||||
void interrupt_43();
|
||||
void interrupt_44();
|
||||
void interrupt_45();
|
||||
void interrupt_46();
|
||||
void interrupt_47();
|
||||
|
||||
// Syscalls
|
||||
void interrupt_0x80();
|
||||
|
||||
|
||||
|
||||
/*********
|
||||
* hwint *
|
||||
*********/
|
||||
|
||||
typedef void(*hwint_handler_t)();
|
||||
|
||||
void hwint_register_handler(unsigned int int_no, hwint_handler_t handler);
|
||||
void hwint_unregister_handler(unsigned int int_no);
|
||||
|
||||
|
||||
|
||||
/***********
|
||||
* syscall *
|
||||
***********/
|
||||
|
||||
enum Kernel_Syscall_Number {
|
||||
KERNEL_SYSCALL_EXIT = 0,
|
||||
};
|
||||
|
||||
#endif
|
|
@ -1,23 +0,0 @@
|
|||
#include "main.h"
|
||||
|
||||
#include <drivers/console.h>
|
||||
|
||||
static void syscall_do_exit(struct IsrRegisters regs);
|
||||
|
||||
void syscall_handler(const struct IsrRegisters regs)
|
||||
{
|
||||
const unsigned int id = regs.eax << 16 >> 16;
|
||||
|
||||
drivers_console_printf("[INFO] syscall: number %u\n", id);
|
||||
|
||||
switch (id) {
|
||||
case KERNEL_SYSCALL_EXIT: syscall_do_exit(regs); break;
|
||||
}
|
||||
}
|
||||
|
||||
void syscall_do_exit(const struct IsrRegisters regs)
|
||||
{
|
||||
const unsigned int exit_code = regs.ebx << 16 >> 16;
|
||||
|
||||
drivers_console_printf("[WARN] syscall: process try to exit with error code %u, haha\n", exit_code);
|
||||
}
|
28
src/main.c
28
src/main.c
|
@ -1,14 +1,20 @@
|
|||
#define KERNAUX_ACCESS_PROTECTED
|
||||
|
||||
#include "paging.h"
|
||||
|
||||
#include "info.h"
|
||||
|
||||
#include "panic.h"
|
||||
#include "protected.h"
|
||||
#include "interrupts.h"
|
||||
|
||||
#include <drivers/console.h>
|
||||
#include <kernaux/generic/display.h>
|
||||
#include <kernaux/macro.h>
|
||||
#include <kernaux/multiboot2.h>
|
||||
#include <kernaux/pfa.h>
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdint.h>
|
||||
|
||||
// Defined in linker script
|
||||
|
@ -23,6 +29,14 @@ static struct Kernel_Info kinfo;
|
|||
static struct KernAux_PFA pfa;
|
||||
static struct Paging paging;
|
||||
|
||||
void my_putc(void *display KERNAUX_UNUSED, char c);
|
||||
void my_vprintf(void *display KERNAUX_UNUSED, const char *format, va_list va);
|
||||
|
||||
static const struct KernAux_Display display = {
|
||||
.putc = my_putc,
|
||||
.vprintf = my_vprintf,
|
||||
};
|
||||
|
||||
void main(
|
||||
const unsigned long multiboot2_info_magic,
|
||||
const struct KernAux_Multiboot2_Info *const multiboot2_info
|
||||
|
@ -33,7 +47,7 @@ void main(
|
|||
panic("Multiboot 2 info magic number is invalid.");
|
||||
}
|
||||
|
||||
KernAux_Multiboot2_Info_print(multiboot2_info, drivers_console_printf);
|
||||
KernAux_Multiboot2_Info_print(multiboot2_info, &display);
|
||||
|
||||
if (!KernAux_Multiboot2_Info_is_valid(multiboot2_info)) {
|
||||
panic("Multiboot 2 info is invalid.");
|
||||
|
@ -65,7 +79,19 @@ void main(
|
|||
paging_load(&paging);
|
||||
paging_enable();
|
||||
|
||||
interrupts_init();
|
||||
|
||||
protected_initialize(&kinfo);
|
||||
|
||||
drivers_console_puts("[INFO] main: Finished.");
|
||||
}
|
||||
|
||||
void my_putc(void *display KERNAUX_UNUSED, char c)
|
||||
{
|
||||
drivers_console_putc(c);
|
||||
}
|
||||
|
||||
void my_vprintf(void *display KERNAUX_UNUSED, const char *format, va_list va)
|
||||
{
|
||||
drivers_console_vprintf(format, va);
|
||||
}
|
||||
|
|
60
src/paging.c
60
src/paging.c
|
@ -18,26 +18,26 @@ void paging_enable()
|
|||
uint32_t cr0 = kernaux_asm_i386_read_cr0();
|
||||
uint32_t cr4 = kernaux_asm_i386_read_cr4();
|
||||
|
||||
assert(cr0 & KERNAUX_ARCH_I386_CR0_PE, "The boot loader should have put us in protected mode.");
|
||||
assert(cr0 & KERNAUX_ARCH_X86_CR0_PE, "The boot loader should have put us in protected mode.");
|
||||
|
||||
// First clear PG and PGE flag, as PGE must be enabled after PG.
|
||||
kernaux_asm_i386_write_cr0(cr0 & ~KERNAUX_ARCH_I386_CR0_PG);
|
||||
kernaux_asm_i386_write_cr4(cr4 & ~(KERNAUX_ARCH_I386_CR4_PGE | KERNAUX_ARCH_I386_CR4_PSE));
|
||||
kernaux_asm_i386_write_cr0(cr0 & ~KERNAUX_ARCH_X86_CR0_PG);
|
||||
kernaux_asm_i386_write_cr4(cr4 & ~(KERNAUX_ARCH_X86_CR4_PGE | KERNAUX_ARCH_X86_CR4_PSE));
|
||||
|
||||
cr0 = kernaux_asm_i386_read_cr0();
|
||||
cr4 = kernaux_asm_i386_read_cr4();
|
||||
|
||||
// Our page table contains 4MB entries.
|
||||
// cr4 |= KERNAUX_ARCH_I386_CR4_PSE;
|
||||
// cr4 |= KERNAUX_ARCH_X86_CR4_PSE;
|
||||
|
||||
kernaux_asm_i386_write_cr4(cr4);
|
||||
|
||||
// First enable paging, then enable global page flag.
|
||||
cr0 |= KERNAUX_ARCH_I386_CR0_PG;
|
||||
cr0 |= KERNAUX_ARCH_X86_CR0_PG;
|
||||
|
||||
kernaux_asm_i386_write_cr0(cr0);
|
||||
|
||||
cr0 |= KERNAUX_ARCH_I386_CR0_WP;
|
||||
cr0 |= KERNAUX_ARCH_X86_CR0_WP;
|
||||
|
||||
kernaux_asm_i386_write_cr0(cr0);
|
||||
kernaux_asm_i386_write_cr4(cr4);
|
||||
|
@ -89,33 +89,33 @@ void mapping(
|
|||
struct KernAux_Arch_I386_PageDir *const page_dir = &paging->page_dir;
|
||||
struct KernAux_Arch_I386_PageTable *const page_table = &paging->page_tables[pde_index];
|
||||
|
||||
struct KernAux_Arch_I386_PDE *const pde = &page_dir->pdes[pde_index];
|
||||
struct KernAux_Arch_I386_PTE *const pte = &page_table->ptes[pte_index];
|
||||
union KernAux_Arch_I386_PDE *const pde = &page_dir->pdes[pde_index];
|
||||
union KernAux_Arch_I386_PTE *const pte = &page_table->ptes[pte_index];
|
||||
|
||||
if (!pde->present) {
|
||||
pde->addr = KERNAUX_ARCH_I386_ADDR_TO_PDE_ADDR(page_table);
|
||||
if (!pde->bitfields.present) {
|
||||
pde->bitfields.addr = KERNAUX_ARCH_I386_ADDR_TO_PDE_ADDR(page_table);
|
||||
|
||||
pde->available1 = 0;
|
||||
pde->page_size = 0;
|
||||
pde->available0 = 0;
|
||||
pde->accessed = 0;
|
||||
pde->cache_disabled = 0;
|
||||
pde->write_through = 0;
|
||||
pde->user = 0;
|
||||
pde->writable = 1;
|
||||
pde->present = 1;
|
||||
pde->bitfields.available1 = 0;
|
||||
pde->bitfields.page_size = 0;
|
||||
pde->bitfields.available0 = 0;
|
||||
pde->bitfields.accessed = 0;
|
||||
pde->bitfields.cache_disabled = 0;
|
||||
pde->bitfields.write_through = 0;
|
||||
pde->bitfields.user = 0;
|
||||
pde->bitfields.writable = 1;
|
||||
pde->bitfields.present = 1;
|
||||
}
|
||||
|
||||
pte->addr = KERNAUX_ARCH_I386_ADDR_TO_PTE_ADDR(phys);
|
||||
pte->bitfields.addr = KERNAUX_ARCH_I386_ADDR_TO_PTE_ADDR(phys);
|
||||
|
||||
pte->available = 1;
|
||||
pte->global = 1;
|
||||
pte->attr_table = 0;
|
||||
pte->dirty = 0;
|
||||
pte->accessed = 0;
|
||||
pte->cache_disabled = 0;
|
||||
pte->write_through = 0;
|
||||
pte->user = 0;
|
||||
pte->writable = 1;
|
||||
pte->present = 1;
|
||||
pte->bitfields.available = 1;
|
||||
pte->bitfields.global = 1;
|
||||
pte->bitfields.attr_table = 0;
|
||||
pte->bitfields.dirty = 0;
|
||||
pte->bitfields.accessed = 0;
|
||||
pte->bitfields.cache_disabled = 0;
|
||||
pte->bitfields.write_through = 0;
|
||||
pte->bitfields.user = 0;
|
||||
pte->bitfields.writable = 1;
|
||||
pte->bitfields.present = 1;
|
||||
}
|
||||
|
|
102
src/protected.c
102
src/protected.c
|
@ -2,7 +2,7 @@
|
|||
|
||||
#include "config.h"
|
||||
#include "info.h"
|
||||
#include "interrupts/main.h"
|
||||
#include "interrupts.h"
|
||||
|
||||
#include <drivers/console.h>
|
||||
#include <drivers/intel_8259_pic.h>
|
||||
|
@ -13,17 +13,11 @@
|
|||
#include <string.h>
|
||||
|
||||
static struct KernAux_Arch_I386_DTR gdt_pointer;
|
||||
static struct KernAux_Arch_I386_DTR idt_pointer;
|
||||
|
||||
static struct KernAux_Arch_I386_DTE gdt_entries[GDT_SIZE];
|
||||
static struct KernAux_Arch_I386_IDTE idt_entries[IDT_SIZE];
|
||||
static struct KernAux_Arch_I386_DTE gdt_entries[GDT_SIZE];
|
||||
|
||||
static struct KernAux_Arch_I386_TSS tss;
|
||||
|
||||
static void gdt_set_gates();
|
||||
static void idt_set_gates();
|
||||
|
||||
static void idt_set_gate(uint8_t num, uint32_t base, uint16_t sel, uint8_t flags);
|
||||
|
||||
void protected_initialize(const struct Kernel_Info *const kinfo)
|
||||
{
|
||||
|
@ -34,7 +28,7 @@ void protected_initialize(const struct Kernel_Info *const kinfo)
|
|||
gdt_set_gates();
|
||||
|
||||
drivers_console_puts("[INFO] protected: Setup IDT.");
|
||||
idt_set_gates();
|
||||
interrupts_setup(GDT_KERNEL_CS_SELECTOR);
|
||||
|
||||
drivers_console_puts("[INFO] protected: Setup TSS.");
|
||||
memset(&tss, 0, sizeof(tss));
|
||||
|
@ -51,12 +45,10 @@ void protected_initialize(const struct Kernel_Info *const kinfo)
|
|||
);
|
||||
|
||||
drivers_console_puts("[INFO] protected: Load IDT.");
|
||||
idt_pointer.size = sizeof(struct KernAux_Arch_I386_IDTE) * IDT_SIZE - 1;
|
||||
idt_pointer.offset = (uint32_t)&idt_entries;
|
||||
kernaux_asm_i386_flush_idt((uint32_t)&idt_pointer);
|
||||
interrupts_load();
|
||||
|
||||
// drivers_console_puts("[INFO] protected: Load TSS.");
|
||||
// kernaux_asm_i386_flush_tss(GDT_TSS_SELECTOR);
|
||||
drivers_console_puts("[INFO] protected: Load TSS.");
|
||||
kernaux_asm_i386_flush_tss(GDT_TSS_SELECTOR);
|
||||
|
||||
drivers_console_puts("[INFO] protected: Enable interrupts.");
|
||||
asm volatile ("sti");
|
||||
|
@ -158,86 +150,8 @@ void gdt_set_gates()
|
|||
.read_write = 0,
|
||||
.conforming_expand_down = 0,
|
||||
.code = 1,
|
||||
.always_1 = 1, // was 0
|
||||
.DPL = 3,
|
||||
.always_1 = 0,
|
||||
.DPL = 0,
|
||||
.present = 1,
|
||||
};
|
||||
}
|
||||
|
||||
void idt_set_gates()
|
||||
{
|
||||
memset(idt_entries, 0, sizeof(idt_entries));
|
||||
|
||||
const uint16_t flags_base = 0x8e;
|
||||
const uint16_t flags_priv_user = 0x60;
|
||||
|
||||
// exception
|
||||
idt_set_gate(0, (uint32_t)interrupt_0, 0x08, flags_base);
|
||||
idt_set_gate(1, (uint32_t)interrupt_1, 0x08, flags_base);
|
||||
idt_set_gate(2, (uint32_t)interrupt_2, 0x08, flags_base);
|
||||
idt_set_gate(3, (uint32_t)interrupt_3, 0x08, flags_base);
|
||||
idt_set_gate(4, (uint32_t)interrupt_4, 0x08, flags_base);
|
||||
idt_set_gate(5, (uint32_t)interrupt_5, 0x08, flags_base);
|
||||
idt_set_gate(6, (uint32_t)interrupt_6, 0x08, flags_base);
|
||||
idt_set_gate(7, (uint32_t)interrupt_7, 0x08, flags_base);
|
||||
idt_set_gate(8, (uint32_t)interrupt_8, 0x08, flags_base);
|
||||
idt_set_gate(9, (uint32_t)interrupt_9, 0x08, flags_base);
|
||||
idt_set_gate(10, (uint32_t)interrupt_10, 0x08, flags_base);
|
||||
idt_set_gate(11, (uint32_t)interrupt_11, 0x08, flags_base);
|
||||
idt_set_gate(12, (uint32_t)interrupt_12, 0x08, flags_base);
|
||||
idt_set_gate(13, (uint32_t)interrupt_13, 0x08, flags_base);
|
||||
idt_set_gate(14, (uint32_t)interrupt_14, 0x08, flags_base);
|
||||
idt_set_gate(15, (uint32_t)interrupt_15, 0x08, flags_base);
|
||||
idt_set_gate(16, (uint32_t)interrupt_16, 0x08, flags_base);
|
||||
idt_set_gate(17, (uint32_t)interrupt_17, 0x08, flags_base);
|
||||
idt_set_gate(18, (uint32_t)interrupt_18, 0x08, flags_base);
|
||||
idt_set_gate(19, (uint32_t)interrupt_19, 0x08, flags_base);
|
||||
idt_set_gate(20, (uint32_t)interrupt_20, 0x08, flags_base);
|
||||
idt_set_gate(21, (uint32_t)interrupt_21, 0x08, flags_base);
|
||||
idt_set_gate(22, (uint32_t)interrupt_22, 0x08, flags_base);
|
||||
idt_set_gate(23, (uint32_t)interrupt_23, 0x08, flags_base);
|
||||
idt_set_gate(24, (uint32_t)interrupt_24, 0x08, flags_base);
|
||||
idt_set_gate(25, (uint32_t)interrupt_25, 0x08, flags_base);
|
||||
idt_set_gate(26, (uint32_t)interrupt_26, 0x08, flags_base);
|
||||
idt_set_gate(27, (uint32_t)interrupt_27, 0x08, flags_base);
|
||||
idt_set_gate(28, (uint32_t)interrupt_28, 0x08, flags_base);
|
||||
idt_set_gate(29, (uint32_t)interrupt_29, 0x08, flags_base);
|
||||
idt_set_gate(30, (uint32_t)interrupt_30, 0x08, flags_base);
|
||||
idt_set_gate(31, (uint32_t)interrupt_31, 0x08, flags_base);
|
||||
|
||||
// hwint: master PIC
|
||||
idt_set_gate(32, (uint32_t)interrupt_32, 0x08, flags_base);
|
||||
idt_set_gate(33, (uint32_t)interrupt_33, 0x08, flags_base);
|
||||
idt_set_gate(34, (uint32_t)interrupt_34, 0x08, flags_base);
|
||||
idt_set_gate(35, (uint32_t)interrupt_35, 0x08, flags_base);
|
||||
idt_set_gate(36, (uint32_t)interrupt_36, 0x08, flags_base);
|
||||
idt_set_gate(37, (uint32_t)interrupt_37, 0x08, flags_base);
|
||||
idt_set_gate(38, (uint32_t)interrupt_38, 0x08, flags_base);
|
||||
idt_set_gate(39, (uint32_t)interrupt_39, 0x08, flags_base);
|
||||
|
||||
// hwint: slave PIC
|
||||
idt_set_gate(40, (uint32_t)interrupt_40, 0x08, flags_base);
|
||||
idt_set_gate(41, (uint32_t)interrupt_41, 0x08, flags_base);
|
||||
idt_set_gate(42, (uint32_t)interrupt_42, 0x08, flags_base);
|
||||
idt_set_gate(43, (uint32_t)interrupt_43, 0x08, flags_base);
|
||||
idt_set_gate(44, (uint32_t)interrupt_44, 0x08, flags_base);
|
||||
idt_set_gate(45, (uint32_t)interrupt_45, 0x08, flags_base);
|
||||
idt_set_gate(46, (uint32_t)interrupt_46, 0x08, flags_base);
|
||||
idt_set_gate(47, (uint32_t)interrupt_47, 0x08, flags_base);
|
||||
|
||||
// syscall
|
||||
idt_set_gate(
|
||||
INT_SYSCALL,
|
||||
(uint32_t)interrupt_0x80,
|
||||
0x08,
|
||||
flags_base | flags_priv_user
|
||||
);
|
||||
}
|
||||
|
||||
void idt_set_gate(uint8_t num, uint32_t base, uint16_t sel, uint8_t flags)
|
||||
{
|
||||
KernAux_Arch_I386_IDTE_set_offset(&idt_entries[num], base);
|
||||
idt_entries[num].selector = sel;
|
||||
idt_entries[num]._zero0 = 0;
|
||||
idt_entries[num].flags = flags;
|
||||
}
|
||||
|
|
21
src/timer.c
21
src/timer.c
|
@ -1,21 +0,0 @@
|
|||
#include "timer.h"
|
||||
|
||||
#include <drivers/console.h>
|
||||
#include <drivers/intel_8253_pit.h>
|
||||
#include <kernaux/asm/i386.h>
|
||||
|
||||
void timer_initialize(unsigned int frequency)
|
||||
{
|
||||
drivers_console_puts("[INFO] timer: Initialize timer.");
|
||||
drivers_intel_8253_pit_initialize(frequency);
|
||||
}
|
||||
|
||||
void timer_register_handler(timer_handler_t handler)
|
||||
{
|
||||
hwint_register_handler(0, handler);
|
||||
}
|
||||
|
||||
void timer_unregister_handler()
|
||||
{
|
||||
hwint_unregister_handler(0);
|
||||
}
|
13
src/timer.h
13
src/timer.h
|
@ -1,13 +0,0 @@
|
|||
#ifndef KERNEL_INCLUDED_TIMER
|
||||
#define KERNEL_INCLUDED_TIMER 1
|
||||
|
||||
#include "interrupts/main.h"
|
||||
|
||||
typedef hwint_handler_t timer_handler_t;
|
||||
|
||||
void timer_initialize(unsigned int frequency);
|
||||
|
||||
void timer_register_handler(timer_handler_t handler);
|
||||
void timer_unregister_handler();
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue