-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
9 changed files
with
353 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
Welcome to Tyr (0x547972), the one-handed OS! | ||
� | ||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,104 @@ | ||
#include "descriptor_tables.h" | ||
|
||
// Get access to ASM functions from C code | ||
extern void gdt_flush(u32int); | ||
extern void idt_flush(u32int); | ||
|
||
// Internal function prototypes | ||
static void init_gdt(); | ||
static void init_idt(); | ||
static void gdt_set_gate(s32int,u32int,u32int,u8int,u8int); | ||
static void idt_set_gate(u8int,u32int,u16int,u8int); | ||
|
||
gdt_entry_t gdt_entries[5]; | ||
gdt_ptr_t gdt_ptr; | ||
idt_entry_t idt_entries[256]; | ||
idt_ptr_t idt_ptr; | ||
|
||
// Initialization routine - zeroes all the interrupt service routines, initializes GDT and IDT | ||
void init_descriptor_tables() { | ||
// Initialize global descriptor table | ||
init_gdt(); | ||
|
||
// Initialize interrupt descriptor table | ||
init_idt(); | ||
} | ||
|
||
static void init_gdt() { | ||
gdt_ptr.limit = (sizeof(gdt_entry_t) * 5) - 1; | ||
gdt_ptr.base = (u32int)&gdt_entries; | ||
|
||
gdt_set_gate(0, 0, 0, 0, 0); // Null segment | ||
gdt_set_gate(1, 0, 0xFFFFFFFF, 0x9A, 0xCF); // Code segment | ||
gdt_set_gate(2, 0, 0xFFFFFFFF, 0x92, 0xCF); // Data segment | ||
gdt_set_gate(3, 0, 0xFFFFFFFF, 0xFA, 0xCF); // User mode code segment | ||
gdt_set_gate(4, 0, 0xFFFFFFFF, 0xF2, 0xCF); // User mode data segment | ||
|
||
gdt_flush((u32int)&gdt_ptr); | ||
} | ||
|
||
// Sets the value of one GDT entry | ||
static void gdt_set_gate(s32int num, u32int base, u32int limit, u8int access, u8int gran) { | ||
gdt_entries[num].base_low = (base & 0xFFFF); | ||
gdt_entries[num].base_middle = (base >> 16) & 0xFF; | ||
gdt_entries[num].base_high = (base >> 24) & 0xFF; | ||
|
||
gdt_entries[num].limit_low = (limit & 0xFFFF); | ||
gdt_entries[num].granularity = (limit >> 16) & 0x0F; | ||
|
||
gdt_entries[num].granularity |= gran & 0xF0; | ||
gdt_entries[num].access = access; | ||
} | ||
|
||
static void init_idt() { | ||
idt_ptr.limit = sizeof(idt_entry_t) * 256 - 1; | ||
idt_ptr.base = (u32int)&idt_entries; | ||
|
||
memset(&idt_entries, 0, sizeof(idt_entry_t) * 256); | ||
|
||
idt_set_gate( 0, (u32int)isr0 , 0x08, 0x8E); | ||
idt_set_gate( 1, (u32int)isr1 , 0x08, 0x8E); | ||
idt_set_gate( 2, (u32int)isr2 , 0x08, 0x8E); | ||
idt_set_gate( 3, (u32int)isr3 , 0x08, 0x8E); | ||
idt_set_gate( 4, (u32int)isr4 , 0x08, 0x8E); | ||
idt_set_gate( 5, (u32int)isr5 , 0x08, 0x8E); | ||
idt_set_gate( 6, (u32int)isr6 , 0x08, 0x8E); | ||
idt_set_gate( 7, (u32int)isr7 , 0x08, 0x8E); | ||
idt_set_gate( 8, (u32int)isr8 , 0x08, 0x8E); | ||
idt_set_gate( 9, (u32int)isr9 , 0x08, 0x8E); | ||
idt_set_gate(10, (u32int)isr10, 0x08, 0x8E); | ||
idt_set_gate(11, (u32int)isr11, 0x08, 0x8E); | ||
idt_set_gate(12, (u32int)isr12, 0x08, 0x8E); | ||
idt_set_gate(13, (u32int)isr13, 0x08, 0x8E); | ||
idt_set_gate(14, (u32int)isr14, 0x08, 0x8E); | ||
idt_set_gate(15, (u32int)isr15, 0x08, 0x8E); | ||
idt_set_gate(16, (u32int)isr16, 0x08, 0x8E); | ||
idt_set_gate(17, (u32int)isr17, 0x08, 0x8E); | ||
idt_set_gate(18, (u32int)isr18, 0x08, 0x8E); | ||
idt_set_gate(19, (u32int)isr19, 0x08, 0x8E); | ||
idt_set_gate(20, (u32int)isr20, 0x08, 0x8E); | ||
idt_set_gate(21, (u32int)isr21, 0x08, 0x8E); | ||
idt_set_gate(22, (u32int)isr22, 0x08, 0x8E); | ||
idt_set_gate(23, (u32int)isr23, 0x08, 0x8E); | ||
idt_set_gate(24, (u32int)isr24, 0x08, 0x8E); | ||
idt_set_gate(25, (u32int)isr25, 0x08, 0x8E); | ||
idt_set_gate(26, (u32int)isr26, 0x08, 0x8E); | ||
idt_set_gate(27, (u32int)isr27, 0x08, 0x8E); | ||
idt_set_gate(28, (u32int)isr28, 0x08, 0x8E); | ||
idt_set_gate(29, (u32int)isr29, 0x08, 0x8E); | ||
idt_set_gate(30, (u32int)isr30, 0x08, 0x8E); | ||
idt_set_gate(31, (u32int)isr31, 0x08, 0x8E); | ||
|
||
idt_flush((u32int)&idt_ptr); | ||
} | ||
|
||
static void idt_set_gate(u8int num, u32int base, u16int sel, u8int flags) { | ||
idt_entries[num].base_lo = base & 0xFFFF; | ||
idt_entries[num].base_hi = (base >> 16) & 0xFFFF; | ||
|
||
idt_entries[num].sel = sel; | ||
idt_entries[num].always0 = 0; | ||
|
||
// Uncomment the OR below when user-mode is implemented, it sets the interrupt gate's privilege level to 3 | ||
idt_entries[num].flags = flags /* | 0x60 */; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
// Defines the interface and structures for initialising the GDT and IDT | ||
|
||
#include "common.h" | ||
|
||
// Value of one GDT entry | ||
// Aattribute 'packed' for GCC not to change any of the alignment in the structure | ||
struct gdt_entry_struct { | ||
u16int limit_low; // Lower 16 bits of the limit | ||
u16int base_low; // Lower 16 bits of the base | ||
u8int base_middle; // Next 8 bits of the base | ||
u8int access; // Access flags, determine what ring this segment can be used in | ||
u8int granularity; | ||
u8int base_high; // Last 8 bits of the base | ||
} __attribute__((packed)); | ||
|
||
typedef struct gdt_entry_struct gdt_entry_t; | ||
|
||
// GDT pointer pointing to the start of array of GDT entries | ||
// In format required by 'lgdt' instruction | ||
struct gdt_ptr_struct { | ||
u16int limit; // Upper 16 bits of all selector limits | ||
u32int base; // Address of the first gdt_entry_t struct | ||
} __attribute__((packed)); | ||
|
||
typedef struct gdt_ptr_struct gdt_ptr_t; | ||
|
||
// Interrupt gate | ||
struct idt_entry_struct { | ||
u16int base_lo; // Lower 16 bits of the address to jump to when this interrupt fires | ||
u16int sel; // Kernel segment selector | ||
u8int always0; // Must always be zero | ||
u8int flags; | ||
u16int base_hi; // Upper 16 bits of the address to jump to | ||
} __attribute__((packed)); | ||
|
||
typedef struct idt_entry_struct idt_entry_t; | ||
|
||
// Pointer to an array of interrupt handlers | ||
// In format suitable for 'lidt' | ||
struct idt_ptr_struct { | ||
u16int limit; | ||
u32int base; // Address of the first element in 'idt_entry_t' array | ||
} __attribute__((packed)); | ||
|
||
typedef struct idt_ptr_struct idt_ptr_t; | ||
|
||
// Extern directives for accessing the addresses of ASM ISR handlers | ||
extern void isr0(); | ||
extern void isr1(); | ||
extern void isr2(); | ||
extern void isr3(); | ||
extern void isr4(); | ||
extern void isr5(); | ||
extern void isr6(); | ||
extern void isr7(); | ||
extern void isr8(); | ||
extern void isr9(); | ||
extern void isr10(); | ||
extern void isr11(); | ||
extern void isr12(); | ||
extern void isr13(); | ||
extern void isr14(); | ||
extern void isr15(); | ||
extern void isr16(); | ||
extern void isr17(); | ||
extern void isr18(); | ||
extern void isr19(); | ||
extern void isr20(); | ||
extern void isr21(); | ||
extern void isr22(); | ||
extern void isr23(); | ||
extern void isr24(); | ||
extern void isr25(); | ||
extern void isr26(); | ||
extern void isr27(); | ||
extern void isr28(); | ||
extern void isr29(); | ||
extern void isr30(); | ||
extern void isr31(); | ||
|
||
// Initialization function | ||
void init_descriptor_tables(); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
; Sets up global descriptor table and interrupt descriptor table. | ||
|
||
[GLOBAL gdt_flush] ; Make 'gdt_flush' accessible from C | ||
|
||
gdt_flush: | ||
mov eax, [esp+4] ; Get pointer to GDT, passed as a parameter | ||
lgdt [eax] ; Load new GDT pointer | ||
|
||
mov ax, 0x10 ; 0x10 is offset in GDT to our data segment | ||
mov ds, ax ; Load all data segment selectors | ||
mov es, ax | ||
mov fs, ax | ||
mov gs, ax | ||
mov ss, ax | ||
jmp 0x08:.flush ; 0x08 is offset to our code segment | ||
.flush: | ||
ret | ||
|
||
|
||
[GLOBAL idt_flush] ; Make 'idt_flush' accessible from C | ||
|
||
idt_flush: | ||
mov eax, [esp+4] ; Get pointer to the IDT, passed as a parameter | ||
lidt [eax] ; Load IDT pointer | ||
ret |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
; Contains interrupt service routine wrappers. | ||
|
||
; Macro creating a stub for an ISR which does NOT pass it's own error code (adds a dummy errcode byte) | ||
%macro ISR_NOERRCODE 1 | ||
[GLOBAL isr%1] | ||
isr%1: | ||
cli ; Disable interrupts firstly | ||
push byte 0 ; Push a dummy error code | ||
push byte %1 ; Push the interrupt number | ||
jmp isr_common_stub ; Go to common handler code | ||
%endmacro | ||
|
||
; Macro creating a stub for an ISR which passes it's own error code. | ||
%macro ISR_ERRCODE 1 | ||
[GLOBAL isr%1] | ||
isr%1: | ||
cli ; Disable interrupts | ||
push byte %1 ; Push the interrupt number | ||
jmp isr_common_stub | ||
%endmacro | ||
|
||
ISR_NOERRCODE 0 | ||
ISR_NOERRCODE 1 | ||
ISR_NOERRCODE 2 | ||
ISR_NOERRCODE 3 | ||
ISR_NOERRCODE 4 | ||
ISR_NOERRCODE 5 | ||
ISR_NOERRCODE 6 | ||
ISR_NOERRCODE 7 | ||
ISR_ERRCODE 8 | ||
ISR_NOERRCODE 9 | ||
ISR_ERRCODE 10 | ||
ISR_ERRCODE 11 | ||
ISR_ERRCODE 12 | ||
ISR_ERRCODE 13 | ||
ISR_ERRCODE 14 | ||
ISR_NOERRCODE 15 | ||
ISR_NOERRCODE 16 | ||
ISR_ERRCODE 17 | ||
ISR_NOERRCODE 18 | ||
ISR_NOERRCODE 19 | ||
ISR_NOERRCODE 20 | ||
ISR_NOERRCODE 21 | ||
ISR_NOERRCODE 22 | ||
ISR_NOERRCODE 23 | ||
ISR_NOERRCODE 24 | ||
ISR_NOERRCODE 25 | ||
ISR_NOERRCODE 26 | ||
ISR_NOERRCODE 27 | ||
ISR_NOERRCODE 28 | ||
ISR_NOERRCODE 29 | ||
ISR_ERRCODE 30 | ||
ISR_NOERRCODE 31 | ||
|
||
[EXTERN isr_handler] ; In isr.c | ||
|
||
; Common ISR stub, saves the processor state, sets up for kernel mode segments, | ||
; calls the C-level fault handler, and finally restores the stack frame | ||
isr_common_stub: | ||
pusha ; Push registers | ||
|
||
mov ax, ds ; Lower 16-bits of eax = ds | ||
push eax ; Save the data segment descriptor | ||
|
||
mov ax, 0x10 ; load the kernel data segment descriptor | ||
mov ds, ax | ||
mov es, ax | ||
mov fs, ax | ||
mov gs, ax | ||
|
||
call isr_handler | ||
|
||
pop ebx ; Reload the original data segment descriptor | ||
mov ds, bx | ||
mov es, bx | ||
mov fs, bx | ||
mov gs, bx | ||
|
||
popa ; Pop registers | ||
add esp, 8 ; Clean up the pushed error code and pushed ISR number | ||
sti | ||
iret ; Pop CS, EIP, EFLAGS, SS, and ESP |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
#include "isr.h" | ||
#include "monitor.h" | ||
|
||
// Called from ASM interrupt handler stub | ||
void isr_handler(registers_t regs) { | ||
monitor_write("recieved interrupt: "); | ||
monitor_write_dec(regs.int_no); | ||
monitor_put('\n'); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
// Interface and structures for high level interrupt service routines | ||
|
||
#include "common.h" | ||
|
||
typedef struct registers { | ||
// Data segment selector | ||
u32int ds; | ||
|
||
// Pushed by pusha | ||
// 'useless_value' instead of 'esp', because it has to do with the current stack context, not what was interrupted (proper 'esp' below) | ||
u32int edi, esi, ebp, useless_value, ebx, edx, ecx, eax; | ||
|
||
// Interrupt number and error code (if applicable) | ||
u32int int_no, err_code; | ||
|
||
// Pushed by the processor automatically | ||
// Proper 'esp' here | ||
u32int eip, cs, eflags, esp, ss; | ||
} registers_t; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters