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>
|
#include <stdint.h>
|
||||||
|
|
||||||
typedef struct InterruptDescriptor_s {
|
typedef struct InterruptDescriptor_s {
|
||||||
uint16_t offset_1;
|
uint16_t offset_lo;
|
||||||
uint16_t selector;
|
uint16_t selector;
|
||||||
uint8_t reserved;
|
uint8_t reserved;
|
||||||
uint8_t attributes;
|
uint8_t attributes;
|
||||||
uint16_t offset_2;
|
uint16_t offset_hi;
|
||||||
} InterruptDescriptor_t;
|
} InterruptDescriptor_t;
|
||||||
|
|
||||||
typedef struct IDTR_s {
|
typedef struct IDTR_s {
|
||||||
uint16_t size;
|
uint16_t size;
|
||||||
InterruptDescriptor_t* IDT;
|
InterruptDescriptor_t* IDT;
|
||||||
} IDTR_t;
|
} __attribute__((packed)) IDTR_t;
|
||||||
|
|
||||||
extern IDTR_t idtr;
|
extern IDTR_t idtr;
|
||||||
extern InterruptDescriptor_t* idt_start;
|
extern InterruptDescriptor_t idt_start;
|
||||||
extern char num_interrupts;
|
extern unsigned char num_interrupts;
|
||||||
|
|
||||||
void setup_idt();
|
void setup_idt();
|
||||||
void write_descriptors();
|
void write_descriptors();
|
||||||
void load_idt();
|
extern void load_idt();
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,12 @@
|
||||||
#ifndef INTERRUPTHANDLERS_H
|
#ifndef INTERRUPTHANDLERS_H
|
||||||
#define INTERRUPTHANDLERS_H
|
#define INTERRUPTHANDLERS_H
|
||||||
#include <stdint.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 {
|
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 interrupt_id, error_code;
|
||||||
uint32_t eip, cs, eflags;
|
uint32_t eip, cs, eflags;
|
||||||
} StateSnapshot_t;
|
} StateSnapshot_t;
|
||||||
|
|
|
||||||
|
|
@ -1,15 +1,19 @@
|
||||||
%define NUM_INTERRUPTS 32
|
%define NUM_INTERRUPTS 255
|
||||||
global idtr, idt_start, num_interrupts
|
global idtr, idt_start, num_interrupts, load_idt
|
||||||
section .idtr
|
|
||||||
|
section .text
|
||||||
|
load_idt:
|
||||||
|
lidt [idtr]
|
||||||
|
ret
|
||||||
|
|
||||||
|
section .idtr align=8
|
||||||
num_interrupts:
|
num_interrupts:
|
||||||
db NUM_INTERRUPTS
|
db NUM_INTERRUPTS
|
||||||
idtr:
|
idtr:
|
||||||
;Normally, the size would be the size of the whole table, but i'm only defining 32 interrupts for now.
|
;IDTR looks like the size (minus 1) and then the pointer to the start of it.
|
||||||
;dw idt_end - idt_start
|
dw 0
|
||||||
dw NUM_INTERRUPTS * 8
|
dd 0
|
||||||
dd idt_start
|
|
||||||
section .idt nobits
|
section .idt nobits
|
||||||
idt_start:
|
idt_start:
|
||||||
resb NUM_INTERRUPTS * 8
|
resb (NUM_INTERRUPTS+1) * 8
|
||||||
idt_end:
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -50,7 +50,8 @@ section .gdt_sect
|
||||||
db 0
|
db 0
|
||||||
db 0b10001001
|
db 0b10001001
|
||||||
dw 0
|
dw 0
|
||||||
|
gdt_end:
|
||||||
gdtr:
|
gdtr:
|
||||||
dw gdtr - gdt - 1
|
dw gdt_end - gdt - 1
|
||||||
dd gdt
|
dd gdt
|
||||||
|
|
||||||
|
|
|
||||||
27
src/idt.c
27
src/idt.c
|
|
@ -1,18 +1,35 @@
|
||||||
#include "idt.h"
|
#include "idt.h"
|
||||||
|
#include "interrupt_handlers.h"
|
||||||
|
|
||||||
void setup_idt() {
|
void setup_idt() {
|
||||||
|
idtr.size = (sizeof(InterruptDescriptor_t) * 256) - 1;
|
||||||
|
idtr.IDT = &idt_start;
|
||||||
write_descriptors();
|
write_descriptors();
|
||||||
load_idt();
|
load_idt();
|
||||||
}
|
}
|
||||||
|
|
||||||
void write_descriptors() {
|
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
|
%assign j 0
|
||||||
%rep 32
|
%rep 255
|
||||||
isr_ %+ j:
|
isr_ %+ j:
|
||||||
ISR_ENTRY j
|
ISR_ENTRY j
|
||||||
%assign j j+1
|
%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.
|
; Generate a table of pointers that point to each of our ISRs. This will be accessed from C to setup our IDT.
|
||||||
isr_ptrs:
|
isr_ptrs:
|
||||||
%assign i 0
|
%assign i 0
|
||||||
%rep 32
|
%rep 255
|
||||||
dd isr_ %+ i
|
dd isr_ %+ i
|
||||||
%assign i i+1
|
%assign i i+1
|
||||||
%endrep
|
%endrep
|
||||||
|
|
|
||||||
|
|
@ -76,7 +76,6 @@ void vga_printdec(uint32_t out) {
|
||||||
void vga_printf(const char* fmt, ...) {
|
void vga_printf(const char* fmt, ...) {
|
||||||
va_list args;
|
va_list args;
|
||||||
va_start(args, fmt);
|
va_start(args, fmt);
|
||||||
|
|
||||||
while(*fmt) {
|
while(*fmt) {
|
||||||
if(*fmt == '%') {
|
if(*fmt == '%') {
|
||||||
fmt++;
|
fmt++;
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,11 @@
|
||||||
*/
|
*/
|
||||||
void i_to_str(uint32_t num, char* buf, int size, int radix) {
|
void i_to_str(uint32_t num, char* buf, int size, int radix) {
|
||||||
//null terminate the string
|
//null terminate the string
|
||||||
|
if(num == 0){
|
||||||
|
buf[0] = '0';
|
||||||
|
buf[1] = '\0';
|
||||||
|
return;
|
||||||
|
}
|
||||||
buf[--size] = '\0';
|
buf[--size] = '\0';
|
||||||
while(size > 0 && (num) != 0){
|
while(size > 0 && (num) != 0){
|
||||||
int isolated_num = num % radix;
|
int isolated_num = num % radix;
|
||||||
|
|
|
||||||
12
src/main.c
12
src/main.c
|
|
@ -4,15 +4,24 @@
|
||||||
#include "kio.h"
|
#include "kio.h"
|
||||||
#include "kttools.h"
|
#include "kttools.h"
|
||||||
#include "kmultiboot.h"
|
#include "kmultiboot.h"
|
||||||
|
#include "idt.h"
|
||||||
//finally, main.
|
//finally, main.
|
||||||
void kern_main(uint32_t multiboot_magic, mb_info_t* multiboot_info)
|
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.
|
//Hello C! Let's get to work in cleaning up our environment a bit and creating some safety.
|
||||||
//First interrupts.
|
//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
|
//wipe the screen
|
||||||
vga_clear();
|
vga_clear();
|
||||||
//We're going to use this buffer as our 8char hex representation for reading mem
|
//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_LOWER:%X\n", multiboot_info->mem_lower);
|
||||||
vga_printf("MEM_UPPER:%X\n", multiboot_info->mem_upper);
|
vga_printf("MEM_UPPER:%X\n", multiboot_info->mem_upper);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue