Loaded IDT!
Many code changes, many undocumented. Documentation and cleanup is next. Fixed a lot of bugs related to IDT structure. Changed the IDT paradigm to be dynamically written isntead of statically to account for nobits on that section. Also added a gdb remote debugger automatic script, for simplicity in debugging.
This commit is contained in:
parent
fbef354410
commit
561c7f9fa7
10 changed files with 72 additions and 28 deletions
6
connect_gdb.sh
Executable file
6
connect_gdb.sh
Executable file
|
|
@ -0,0 +1,6 @@
|
|||
#!/bin/bash
|
||||
|
||||
i686-elf-gdb build/ukern.elf \
|
||||
-ex "target remote localhost:1234" \
|
||||
-ex "break start" \
|
||||
-ex "continue"
|
||||
|
|
@ -3,24 +3,24 @@
|
|||
#include <stdint.h>
|
||||
|
||||
typedef struct InterruptDescriptor_s {
|
||||
uint16_t offset_1;
|
||||
uint16_t offset_lo;
|
||||
uint16_t selector;
|
||||
uint8_t reserved;
|
||||
uint8_t attributes;
|
||||
uint16_t offset_2;
|
||||
uint16_t offset_hi;
|
||||
} InterruptDescriptor_t;
|
||||
|
||||
typedef struct IDTR_s {
|
||||
uint16_t size;
|
||||
InterruptDescriptor_t* IDT;
|
||||
} IDTR_t;
|
||||
} __attribute__((packed)) IDTR_t;
|
||||
|
||||
extern IDTR_t idtr;
|
||||
extern InterruptDescriptor_t* idt_start;
|
||||
extern char num_interrupts;
|
||||
extern InterruptDescriptor_t idt_start;
|
||||
extern unsigned char num_interrupts;
|
||||
|
||||
void setup_idt();
|
||||
void write_descriptors();
|
||||
void load_idt();
|
||||
extern void load_idt();
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -1,10 +1,12 @@
|
|||
#ifndef INTERRUPTHANDLERS_H
|
||||
#define INTERRUPTHANDLERS_H
|
||||
#include <stdint.h>
|
||||
extern void* isr_ptrs;
|
||||
|
||||
extern void (*isr_ptrs[])(void);
|
||||
|
||||
//Struct is built "backwards" since it is pushed in this order.
|
||||
typedef struct StateSnapshot_s {
|
||||
uint32_t eax, ecx, edx, ebx, esp, esi, edi;
|
||||
uint32_t edi, esi, esp, ebx, edx, ecx, eax;
|
||||
uint32_t interrupt_id, error_code;
|
||||
uint32_t eip, cs, eflags;
|
||||
} StateSnapshot_t;
|
||||
|
|
|
|||
|
|
@ -1,15 +1,19 @@
|
|||
%define NUM_INTERRUPTS 32
|
||||
global idtr, idt_start, num_interrupts
|
||||
section .idtr
|
||||
%define NUM_INTERRUPTS 255
|
||||
global idtr, idt_start, num_interrupts, load_idt
|
||||
|
||||
section .text
|
||||
load_idt:
|
||||
lidt [idtr]
|
||||
ret
|
||||
|
||||
section .idtr align=8
|
||||
num_interrupts:
|
||||
db NUM_INTERRUPTS
|
||||
idtr:
|
||||
;Normally, the size would be the size of the whole table, but i'm only defining 32 interrupts for now.
|
||||
;dw idt_end - idt_start
|
||||
dw NUM_INTERRUPTS * 8
|
||||
dd idt_start
|
||||
;IDTR looks like the size (minus 1) and then the pointer to the start of it.
|
||||
dw 0
|
||||
dd 0
|
||||
section .idt nobits
|
||||
idt_start:
|
||||
resb NUM_INTERRUPTS * 8
|
||||
idt_end:
|
||||
resb (NUM_INTERRUPTS+1) * 8
|
||||
|
||||
|
|
|
|||
|
|
@ -50,7 +50,8 @@ section .gdt_sect
|
|||
db 0
|
||||
db 0b10001001
|
||||
dw 0
|
||||
gdt_end:
|
||||
gdtr:
|
||||
dw gdtr - gdt - 1
|
||||
dw gdt_end - gdt - 1
|
||||
dd gdt
|
||||
|
||||
|
|
|
|||
27
src/idt.c
27
src/idt.c
|
|
@ -1,18 +1,35 @@
|
|||
#include "idt.h"
|
||||
|
||||
#include "interrupt_handlers.h"
|
||||
|
||||
void setup_idt() {
|
||||
idtr.size = (sizeof(InterruptDescriptor_t) * 256) - 1;
|
||||
idtr.IDT = &idt_start;
|
||||
write_descriptors();
|
||||
load_idt();
|
||||
}
|
||||
|
||||
void write_descriptors() {
|
||||
|
||||
for(int i = 0; i < num_interrupts; i++) {
|
||||
for(int i = 0; i <= num_interrupts; i++) {
|
||||
uint32_t current_isr = (uint32_t)isr_ptrs[i];
|
||||
InterruptDescriptor_t* current_idt_entry = idtr.IDT + (i*8);
|
||||
|
||||
// Offset bits 0-15
|
||||
current_idt_entry->offset_lo = current_isr & 0xFFFF;
|
||||
current_idt_entry->offset_hi = current_isr >> 16;
|
||||
current_idt_entry->selector = 0x08; // GDT index = 1 (kernel code seg), TI = 0 (pull from GDT, not LDT), RPL = 0 (ring 0)
|
||||
//Attributes is a complex field. Lets break it down:
|
||||
//First 4 bits is the gate type. Task, interrupt, trap.
|
||||
//bit 44 is a zero
|
||||
//Bits 45-46 is DPL - or what rings can access the interrupt via the INT instruction.
|
||||
if(i < 32)
|
||||
//All interrupt gates, only R0 can access.
|
||||
current_idt_entry->attributes = 0b10001110;
|
||||
else
|
||||
//All interrupt gates, all rings can use these ints.
|
||||
current_idt_entry->attributes = 0b11101110;
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void load_idt() {
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ isr_%1:
|
|||
|
||||
|
||||
%assign j 0
|
||||
%rep 32
|
||||
%rep 255
|
||||
isr_ %+ j:
|
||||
ISR_ENTRY j
|
||||
%assign j j+1
|
||||
|
|
@ -42,7 +42,7 @@ isr_%1:
|
|||
; Generate a table of pointers that point to each of our ISRs. This will be accessed from C to setup our IDT.
|
||||
isr_ptrs:
|
||||
%assign i 0
|
||||
%rep 32
|
||||
%rep 255
|
||||
dd isr_ %+ i
|
||||
%assign i i+1
|
||||
%endrep
|
||||
|
|
|
|||
|
|
@ -76,7 +76,6 @@ void vga_printdec(uint32_t out) {
|
|||
void vga_printf(const char* fmt, ...) {
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
|
||||
while(*fmt) {
|
||||
if(*fmt == '%') {
|
||||
fmt++;
|
||||
|
|
|
|||
|
|
@ -30,6 +30,11 @@
|
|||
*/
|
||||
void i_to_str(uint32_t num, char* buf, int size, int radix) {
|
||||
//null terminate the string
|
||||
if(num == 0){
|
||||
buf[0] = '0';
|
||||
buf[1] = '\0';
|
||||
return;
|
||||
}
|
||||
buf[--size] = '\0';
|
||||
while(size > 0 && (num) != 0){
|
||||
int isolated_num = num % radix;
|
||||
|
|
|
|||
12
src/main.c
12
src/main.c
|
|
@ -4,15 +4,24 @@
|
|||
#include "kio.h"
|
||||
#include "kttools.h"
|
||||
#include "kmultiboot.h"
|
||||
|
||||
#include "idt.h"
|
||||
//finally, main.
|
||||
void kern_main(uint32_t multiboot_magic, mb_info_t* multiboot_info)
|
||||
{
|
||||
//Hello C! Let's get to work in cleaning up our environment a bit and creating some safety.
|
||||
//First interrupts.
|
||||
vga_clear();
|
||||
vga_printf("IDT base = %X", idtr.IDT);
|
||||
|
||||
|
||||
setup_idt();
|
||||
|
||||
vga_printf("IDT test :)");
|
||||
int x = 5;
|
||||
int y = 1;
|
||||
x = x / (y-1);
|
||||
|
||||
vga_printf("%d", x);
|
||||
//wipe the screen
|
||||
vga_clear();
|
||||
//We're going to use this buffer as our 8char hex representation for reading mem
|
||||
|
|
@ -28,5 +37,6 @@ void kern_main(uint32_t multiboot_magic, mb_info_t* multiboot_info)
|
|||
|
||||
vga_printf("MEM_LOWER:%X\n", multiboot_info->mem_lower);
|
||||
vga_printf("MEM_UPPER:%X\n", multiboot_info->mem_upper);
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue