Interrupts are working!!!!111!!!!! zomg

alentours-dev
q3k 2012-05-07 16:53:06 +00:00
parent 6f065bc9b2
commit b67c670e38
9 changed files with 89 additions and 76 deletions

View File

@ -84,15 +84,16 @@ hdd.img: kernel.bin
emulate-nohdd-debug: kernel.bin
@echo "[i] Starting GDB..."
@gnome-terminal -x /bin/bash -c "gdb"
@echo -e "target remote localhost:1234\n" > gdbcommands
@terminal -x /bin/bash -c "sleep 1 && gdb -x gdbcommands && rm gdbcommands" &
@echo "[i] Starting QEmu..."
@qemu -kernel kernel.bin -S -gdb tcp::1234
@qemu-system-x86_64 -S -gdb tcp::1234 -d int -smp 4 -kernel ../Loader/loader.bin -initrd kernel.bin
emulate-nohdd: kernel.bin
@echo "[i] Building loader..."
@pushd ../Loader > /dev/null && $(MAKE) -f Makefile loader.bin && popd > /dev/null
@echo "[i] Starting QEMU..."
@qemu-system-x86_64 -smp 4 -kernel ../Loader/loader.bin -initrd kernel.bin
@qemu-system-x86_64 -d int -smp 4 -kernel ../Loader/loader.bin -initrd kernel.bin
emulate: hdd.img
@echo "[i] Starting QEmu..."

View File

@ -20,7 +20,7 @@ struct S_IDT_ENTRY {
u16 OffsetMiddle;
u32 OffsetHigh;
u64 Reserved;
u32 Reserved;
} __attribute__ ((packed));
typedef struct S_IDT_ENTRY T_IDT_ENTRY;

View File

@ -18,7 +18,7 @@ void kprint(const s8 *szString);
void kputi(s32 Number);
void kprintf(const s8 *Format, ...);
void kdump(u8 *bData, u32 Length);
void kprint_hex(u32 Number);
void kprint_hex(u64 Number);
void kstdio_set_globals(u8 line, u8 cur_x, u8 cur_y);
s32 kmemcmp(u8 *MemA, u8 *MemB, u32 Length);

View File

@ -80,6 +80,8 @@ void paging_set_ml4(u64 ML4Physical);
u8 paging_get_physical(u64 Virtual, u64 *Physical);
u8 paging_get_physical_ex(u64 Virtual, u64 *Physical,T_PAGING_ML4 *ML4);
void paging_kernel_initialize(u64 KernelVirtualStart, u64 KernelPhysicalStart, u64 KernelSize);
// The temporary page is a page you can use to access some temporary physical
// location. There is only one page, 4096 bytes large. Deal with it.
void paging_temp_page_setup(T_LOAD_CONTEXT *LoadContext);

View File

@ -1,11 +1,11 @@
;BITS 32
;section .text
BITS 64
section .text
;global interrupts_lidt
;extern g_idt_ptr
;extern g_Interrupts
;interrupts_lidt:
; lidt [g_idt_ptr]
; lidt [g_Interrupts]
; ret
;global interrupts_irq_sample
@ -13,3 +13,4 @@
; mov eax, 0xB8000
; mov byte [eax], 0x45
; iret

View File

@ -11,7 +11,7 @@ struct {
// IRQ/APIC/Whatever
T_INTERRUPTS_CHIP Chip;
} g_Interrupts;
} __attribute__((packed)) g_Interrupts;
// This shit does nothing
void interrupts_set_chip(T_INTERRUPTS_CHIP Chip)
@ -27,54 +27,43 @@ void interrupts_set_chip(T_INTERRUPTS_CHIP Chip)
"interrupts.\n");
}
void interrupts_lidt(void)
{
__asm__ __volatile__("lidt (%0)" : : "p"(&g_Interrupts.IDTPointer));
}
u8 interrupts_init_idt(void)
{
g_Interrupts.IDTPointer.Limit = 256 * 16;
u64 Physical = 0;
u8 Result = paging_get_physical((u64)g_Interrupts.IDTEntries, &Physical);
if (!Result)
return 0;
kprintf("[i] Setting up IDT at 0x%x (0x%x Virtual).\n", Physical, g_Interrupts.IDTEntries);
g_Interrupts.IDTPointer.Base = Physical;
g_Interrupts.IDTPointer.Base = (u64)g_Interrupts.IDTEntries;
kprintf("[i] Setting up IDT at 0x%x.\n", g_Interrupts.IDTEntries);
kprintf("[i] IDT Entry size %i bytes.\n", sizeof(T_IDT_ENTRY));
// Null those entries!
for (u16 i = 0; i < 256; i++)
{
// Maybe I should access the struct's members...
// Or i can just cast that to to u64's and null them.
// Or i can just cast that to to u32's and null them.
// This will set the Present flag to 0 either way
*((u64 *)(&g_Interrupts.IDTEntries[i])) = 0;
*(((u64 *)(&g_Interrupts.IDTEntries[i]) + 1)) = 0;
*(((u64 *)(&g_Interrupts.IDTEntries[i]) + 2)) = 0;
*(((u64 *)(&g_Interrupts.IDTEntries[i]) + 3)) = 0;
}
return 1;
}
/*
// This creates an ASM stub for
// This creates a 12-byte ASM stub for a handler
void interrupts_create_stub(T_ISR_STUB *Destination, u32 Address)
void interrupts_create_stub(T_ISR_STUB *Destination, u64 Address)
{
// The ASM code is as follows:
// cli
// pushad
// mov eax, Handler
// call eax
// popad
// sti
// iret
Destination->Code1 = 0x60FA; // pushad, cli
Destination->Code2 = 0xB8; // mov eax,
Destination->Code1 = 0x57565552515350fa;
Destination->Code2 = 0x5341524151415041;
Destination->Code3 = 0x5741564155415441;
Destination->Code4 = 0xb848;
Destination->Handler = Address; // Address
Destination->Code3 = 0xFB61D0FF; // sti, popad, call eax
Destination->Code4 = 0xCF; // iret
Destination->Code5 = 0x5d415e415f41d0ff;
Destination->Code6 = 0x59415a415b415c41;
Destination->Code7 = 0x5b595a5d5e5f5841;
Destination->Code8 = 0xcf48fb58;
}
/*
void interrupts_setup_irq(u8 IRQ, void *Handler)
{
if (g_interrupts_chip != E_INTERRUPTS_CHIP_PIC)
@ -96,63 +85,57 @@ void interrupts_dump_idt_ptr(void)
kprintf("[i] IDT Pointer structure:\n");
kprintf(" Base: 0x%x.\n", g_idt_ptr.Base);
kprintf(" Limit: 0x%x.\n", g_idt_ptr.Limit);
}
}*/
void interrupts_dump_idt_entry(u8 Interrupt)
{
u32 *dwEntry = (u32 *)&g_idt_entries[Interrupt];
kprintf("[i] IDT Entry for interrupt %x:\n", Interrupt);
kprintf(" DW Low : 0x%x.\n", *dwEntry);
kprintf(" DW High: 0x%x.\n", *(dwEntry + 1));
T_IDT_ENTRY Entry = g_idt_entries[Interrupt];
kprintf(" Offset: 0x%x.\n", (Entry.OffsetHigh << 16) + Entry.OffsetLow);
kprintf("[i] IDT Entry for interrupt %x, %x:\n", Interrupt, &g_Interrupts.IDTEntries[Interrupt]);
T_IDT_ENTRY Entry = g_Interrupts.IDTEntries[Interrupt];
kprintf(" Offset: 0x%x.\n", (u64 )((u64)Entry.OffsetHigh << 32) + ((u64)Entry.OffsetMiddle << 16) + (u64)Entry.OffsetLow);
kprintf(" Selector: %u.\n", Entry.Selector);
kprintf(" Zero: %u.\n", Entry.Zero);
kprintf(" P: %u.\n", (Entry.Type >> 7) & 0b1);
kprintf(" DPL: %u.\n", (Entry.Type >> 5) & 0b11);
kprintf(" S: %u.\n", (Entry.Type >> 4) & 0b1);
kprintf(" Gate type: %u.\n", Entry.Type & 0b1111);
kprintf(" P: %u.\n", Entry.Present);
kprintf(" DPL: %u.\n", Entry.DPL);
kprintf(" S: %u.\n", Entry.Selector);
kprintf(" Gate type: %u.\n", Entry.Type);
}
void interrupts_setup_isr_raw(u8 Interrupt, void *ASMHandler, \
T_INTERRUPTS_RING Ring)
{
u32 uASMHandler = (u32)ASMHandler;
g_idt_entries[Interrupt].OffsetLow = uASMHandler & 0xFFFF;
g_idt_entries[Interrupt].OffsetHigh = (uASMHandler >> 16) & 0xFFFF;
g_idt_entries[Interrupt].Selector = 0x08;
g_idt_entries[Interrupt].Zero = 0;
u8 Type = 0;
Type |= (1 << 7);
Type |= (Ring << 5);
Type |= (0 << 4);
Type |= 0xE;
g_idt_entries[Interrupt].Type = Type;
u64 uASMHandler = (u64)ASMHandler;
g_Interrupts.IDTEntries[Interrupt].OffsetLow = uASMHandler & 0xFFFF;
g_Interrupts.IDTEntries[Interrupt].OffsetMiddle = (uASMHandler >> 16) & 0xFFFF;
g_Interrupts.IDTEntries[Interrupt].OffsetHigh = uASMHandler >> 32;
g_Interrupts.IDTEntries[Interrupt].Selector = 0x18;
g_Interrupts.IDTEntries[Interrupt].Zero1 = 0;
g_Interrupts.IDTEntries[Interrupt].Zero2 = 0;
g_Interrupts.IDTEntries[Interrupt].DPL = Ring;
g_Interrupts.IDTEntries[Interrupt].Present = 1;
g_Interrupts.IDTEntries[Interrupt].Type = 0b1111;
}
void interrupts_setup_isr(u8 Interrupt, void *Handler, \
T_INTERRUPTS_RING Ring)
{
interrupts_create_stub(&g_isr_stubs[Interrupt], (u32)Handler);
interrupts_create_stub(&g_Interrupts.ISRStubs[Interrupt], (u64)Handler);
u32 ASMHandler = (u32)&g_isr_stubs[Interrupt];
u64 ASMHandler = (u64)&g_Interrupts.ISRStubs[Interrupt];
interrupts_setup_isr_raw(Interrupt, (void*)ASMHandler, Ring);
}
void interrupts_delete_isr(u8 Interrupt)
/*void interrupts_delete_isr(u8 Interrupt)
{
*((u32*)&g_idt_entries[Interrupt]) = 0;
}
*/
void interrupts_init_simple(void)
{
interrupts_set_chip(E_INTERRUPTS_CHIP_PIC);
interrupts_init_idt();
interrupts_lidt();
}
/*
void interrupts_irq_finish(u8 IRQ)
{
if (g_interrupts_chip == E_INTERRUPTS_CHIP_PIC)

View File

@ -26,6 +26,11 @@ extern u64 _end;
u8 test[4096 * 2];
u8 test2[4096 * 2];
void interrupts_test(void)
{
kprintf("Hello from an interrupt!\n");
}
// Real kernel entry point, called from loader
void kmain(u32 LoadContextAddress)
{
@ -67,6 +72,7 @@ void kmain(u32 LoadContextAddress)
kprintf("[i] Loader physical: %x-%x.\n", LoadContext->LoaderPhysicalStart, LoadContext->LoaderPhysicalEnd);
kprintf("[i] Kernel virtual: %x-%x.\n", &_start, &_end);
paging_kernel_initialize((u64)&_start, LoadContext->KernelPhysicalStart, LoadContext->KernelPhysicalEnd - LoadContext->KernelPhysicalStart);
paging_temp_page_setup(LoadContext);
paging_minivmm_setup((u64)&_end, 0xFF000000 + 511 * 4096);
@ -81,7 +87,10 @@ void kmain(u32 LoadContextAddress)
apic_enable_lapic();
//interrupts_init_simple();
interrupts_init_simple();
interrupts_setup_isr(0x80, interrupts_test, E_INTERRUPTS_RING0);
interrupts_dump_idt_entry(0x80);
__asm__ volatile("int $0x80");
for (;;) {}
/*exceptions_init_simple();
pic_init(0, 0);

View File

@ -105,7 +105,7 @@ void kprintf(const s8 *szFormat, ...)
break;
case 'X':
case 'x':
; u32 bData = va_arg(ap, u32);
; u64 bData = va_arg(ap, u64);
kprint_hex(bData);
break;
default:
@ -184,9 +184,9 @@ void kdump_nibble(u8 Nibble)
kputch(Nibble + 55);
}
void kprint_hex(u32 Number)
void kprint_hex(u64 Number)
{
for (s8 i = 3; i >= 0; i--)
for (s8 i = 7; i >= 0; i--)
{
u8 Byte = (Number >> (i << 3)) & 0xFF; //switch i bytes to the right and mask as byte
kdump_nibble((Byte >> 4) & 0x0F); //high nibble

View File

@ -7,6 +7,10 @@
struct {
T_PAGING_TAB_ENTRY *TempPage; // For temp page mapping.
u64 TempPageVirtual;
u64 KernelVirtualStart;
u64 KernelPhysicalStart;
u64 KernelSize;
} g_KernelPaging;
struct {
@ -74,10 +78,23 @@ void paging_temp_page_set_physical(u64 Physical)
__asm__ volatile("invlpg %0" :: "m"(*(u32 *)g_KernelPaging.TempPageVirtual));
}
void paging_kernel_initialize(u64 KernelVirtualStart, u64 KernelPhysicalStart, u64 KernelSize)
{
g_KernelPaging.KernelVirtualStart = KernelVirtualStart;
g_KernelPaging.KernelPhysicalStart = KernelPhysicalStart;
g_KernelPaging.KernelSize = KernelSize;
}
u8 paging_get_physical_ex(u64 Virtual, u64 *Physical, T_PAGING_ML4 *ML4)
{
PANIC("not implemented!");
return 0;
if (Virtual < g_KernelPaging.KernelVirtualStart || Virtual > g_KernelPaging.KernelVirtualStart + g_KernelPaging.KernelSize)
{
PANIC("not implemented");
return 0;
}
*Physical = Virtual - g_KernelPaging.KernelVirtualStart + g_KernelPaging.KernelPhysicalStart;
return 1;
}
u8 paging_get_physical(u64 Virtual, u64 *Physical)