forked from Bananymous/banan-os
Kernel: Finally managed to get 64-bit working
I had weird problems with interrupts but everything should work now
This commit is contained in:
parent
c4670f49d4
commit
b315fdc27f
|
@ -0,0 +1,8 @@
|
||||||
|
ARCH_CFLAGS=
|
||||||
|
ARCH_CPPFLAGS=
|
||||||
|
KERNEL_ARCH_CFLAGS=
|
||||||
|
KERNEL_ARCH_CPPFLAGS=
|
||||||
|
|
||||||
|
ARCH_FREEOBJS=\
|
||||||
|
|
||||||
|
ARCH_HOSTEDOBJS=\
|
|
@ -0,0 +1,236 @@
|
||||||
|
#include <BAN/Errors.h>
|
||||||
|
#include <kernel/IDT.h>
|
||||||
|
#include <kernel/InterruptController.h>
|
||||||
|
#include <kernel/kmalloc.h>
|
||||||
|
#include <kernel/Panic.h>
|
||||||
|
|
||||||
|
#define REGISTER_ISR_HANDLER(i) register_interrupt_handler(i, isr ## i)
|
||||||
|
#define REGISTER_IRQ_HANDLER(i) register_interrupt_handler(IRQ_VECTOR_BASE + i, irq ## i)
|
||||||
|
|
||||||
|
namespace IDT
|
||||||
|
{
|
||||||
|
|
||||||
|
struct GateDescriptor
|
||||||
|
{
|
||||||
|
uint16_t offset1;
|
||||||
|
uint16_t selector;
|
||||||
|
uint8_t IST;
|
||||||
|
uint8_t flags;
|
||||||
|
uint16_t offset2;
|
||||||
|
uint32_t offset3;
|
||||||
|
uint32_t reserved;
|
||||||
|
} __attribute__((packed));
|
||||||
|
|
||||||
|
struct IDTR
|
||||||
|
{
|
||||||
|
uint16_t size;
|
||||||
|
uint64_t offset;
|
||||||
|
} __attribute__((packed));
|
||||||
|
|
||||||
|
static IDTR s_idtr;
|
||||||
|
static GateDescriptor* s_idt = nullptr;
|
||||||
|
|
||||||
|
static void (*s_irq_handlers[0x10])() { nullptr };
|
||||||
|
|
||||||
|
static const char* isr_exceptions[] =
|
||||||
|
{
|
||||||
|
"Division Error",
|
||||||
|
"Debug",
|
||||||
|
"Non-maskable Interrupt",
|
||||||
|
"Breakpoint",
|
||||||
|
"Overflow",
|
||||||
|
"Bound Range Exception",
|
||||||
|
"Invalid Opcode",
|
||||||
|
"Device Not Available",
|
||||||
|
"Double Fault",
|
||||||
|
"Coprocessor Segment Overrun",
|
||||||
|
"Invalid TSS",
|
||||||
|
"Segment Not Present",
|
||||||
|
"Stack-Segment Fault",
|
||||||
|
"General Protection Fault",
|
||||||
|
"Page Fault",
|
||||||
|
"Unknown Exception 0x0F",
|
||||||
|
"x87 Floating-Point Exception",
|
||||||
|
"Alignment Check",
|
||||||
|
"Machine Check",
|
||||||
|
"SIMD Floating-Point Exception",
|
||||||
|
"Virtualization Exception",
|
||||||
|
"Control Protection Exception",
|
||||||
|
"Unknown Exception 0x16",
|
||||||
|
"Unknown Exception 0x17",
|
||||||
|
"Unknown Exception 0x18",
|
||||||
|
"Unknown Exception 0x19",
|
||||||
|
"Unknown Exception 0x1A",
|
||||||
|
"Unknown Exception 0x1B",
|
||||||
|
"Hypervisor Injection Exception",
|
||||||
|
"VMM Communication Exception",
|
||||||
|
"Security Exception",
|
||||||
|
"Unkown Exception 0x1F",
|
||||||
|
};
|
||||||
|
|
||||||
|
extern "C" void cpp_isr_handler(uint64_t isr, uint64_t error)
|
||||||
|
{
|
||||||
|
uint64_t rax, rbx, rcx, rdx, rsp, rbp;
|
||||||
|
uint64_t cr0, cr2, cr3, cr4;
|
||||||
|
asm volatile("":"=a"(rax),"=b"(rbx),"=c"(rcx),"=d"(rdx));
|
||||||
|
asm volatile("movq %%rsp, %%rax":"=a"(rsp));
|
||||||
|
asm volatile("movq %%rbp, %%rax":"=a"(rbp));
|
||||||
|
asm volatile("movq %%cr0, %%rax":"=a"(cr0));
|
||||||
|
asm volatile("movq %%cr2, %%rax":"=a"(cr2));
|
||||||
|
asm volatile("movq %%cr3, %%rax":"=a"(cr3));
|
||||||
|
asm volatile("movq %%cr4, %%rax":"=a"(cr4));
|
||||||
|
|
||||||
|
Kernel::Panic(
|
||||||
|
"{} (error code: 0x{16H})\r\n"
|
||||||
|
"Register dump\r\n"
|
||||||
|
"rax=0x{16H}, rbx=0x{16H}, rcx=0x{16H}, rdx=0x{16H}\r\n"
|
||||||
|
"rsp=0x{16H}, rbp=0x{16H}\r\n"
|
||||||
|
"CR0=0x{16H}, CR2=0x{16H}, CR3=0x{16H}, CR4=0x{16H}\r\n",
|
||||||
|
isr_exceptions[isr], error, rax, rbx, rcx, rdx, rsp, rbp, cr0, cr2, cr3, cr4
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" void cpp_irq_handler(uint64_t irq)
|
||||||
|
{
|
||||||
|
if (s_irq_handlers[irq])
|
||||||
|
s_irq_handlers[irq]();
|
||||||
|
else
|
||||||
|
dprintln("no handler for irq 0x{2H}\n", irq);
|
||||||
|
|
||||||
|
InterruptController::Get().EOI(irq);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void flush_idt()
|
||||||
|
{
|
||||||
|
asm volatile("lidt %0"::"m"(s_idtr));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void register_interrupt_handler(uint8_t index, void (*f)())
|
||||||
|
{
|
||||||
|
GateDescriptor& descriptor = s_idt[index];
|
||||||
|
descriptor.offset1 = (uint16_t)((uint64_t)f >> 0);
|
||||||
|
descriptor.offset2 = (uint16_t)((uint64_t)f >> 16);
|
||||||
|
descriptor.offset3 = (uint32_t)((uint64_t)f >> 32);
|
||||||
|
|
||||||
|
descriptor.selector = 0x08;
|
||||||
|
descriptor.IST = 0;
|
||||||
|
descriptor.flags = 0x8E;
|
||||||
|
}
|
||||||
|
|
||||||
|
void register_irq_handler(uint8_t irq, void (*f)())
|
||||||
|
{
|
||||||
|
s_irq_handlers[irq] = f;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" void isr0();
|
||||||
|
extern "C" void isr1();
|
||||||
|
extern "C" void isr2();
|
||||||
|
extern "C" void isr3();
|
||||||
|
extern "C" void isr4();
|
||||||
|
extern "C" void isr5();
|
||||||
|
extern "C" void isr6();
|
||||||
|
extern "C" void isr7();
|
||||||
|
extern "C" void isr8();
|
||||||
|
extern "C" void isr9();
|
||||||
|
extern "C" void isr10();
|
||||||
|
extern "C" void isr11();
|
||||||
|
extern "C" void isr12();
|
||||||
|
extern "C" void isr13();
|
||||||
|
extern "C" void isr14();
|
||||||
|
extern "C" void isr15();
|
||||||
|
extern "C" void isr16();
|
||||||
|
extern "C" void isr17();
|
||||||
|
extern "C" void isr18();
|
||||||
|
extern "C" void isr19();
|
||||||
|
extern "C" void isr20();
|
||||||
|
extern "C" void isr21();
|
||||||
|
extern "C" void isr22();
|
||||||
|
extern "C" void isr23();
|
||||||
|
extern "C" void isr24();
|
||||||
|
extern "C" void isr25();
|
||||||
|
extern "C" void isr26();
|
||||||
|
extern "C" void isr27();
|
||||||
|
extern "C" void isr28();
|
||||||
|
extern "C" void isr29();
|
||||||
|
extern "C" void isr30();
|
||||||
|
extern "C" void isr31();
|
||||||
|
|
||||||
|
extern "C" void irq0();
|
||||||
|
extern "C" void irq1();
|
||||||
|
extern "C" void irq2();
|
||||||
|
extern "C" void irq3();
|
||||||
|
extern "C" void irq4();
|
||||||
|
extern "C" void irq5();
|
||||||
|
extern "C" void irq6();
|
||||||
|
extern "C" void irq7();
|
||||||
|
extern "C" void irq8();
|
||||||
|
extern "C" void irq9();
|
||||||
|
extern "C" void irq10();
|
||||||
|
extern "C" void irq11();
|
||||||
|
extern "C" void irq12();
|
||||||
|
extern "C" void irq13();
|
||||||
|
extern "C" void irq14();
|
||||||
|
extern "C" void irq15();
|
||||||
|
|
||||||
|
void initialize()
|
||||||
|
{
|
||||||
|
s_idt = (GateDescriptor*)kmalloc_eternal(0x100 * sizeof(GateDescriptor));
|
||||||
|
memset(s_idt, 0x00, 0x100 * sizeof(GateDescriptor));
|
||||||
|
|
||||||
|
s_idtr.offset = (uint64_t)s_idt;
|
||||||
|
s_idtr.size = 0x100 * sizeof(GateDescriptor) - 1;
|
||||||
|
|
||||||
|
REGISTER_ISR_HANDLER(0);
|
||||||
|
REGISTER_ISR_HANDLER(1);
|
||||||
|
REGISTER_ISR_HANDLER(2);
|
||||||
|
REGISTER_ISR_HANDLER(3);
|
||||||
|
REGISTER_ISR_HANDLER(4);
|
||||||
|
REGISTER_ISR_HANDLER(5);
|
||||||
|
REGISTER_ISR_HANDLER(6);
|
||||||
|
REGISTER_ISR_HANDLER(7);
|
||||||
|
REGISTER_ISR_HANDLER(8);
|
||||||
|
REGISTER_ISR_HANDLER(9);
|
||||||
|
REGISTER_ISR_HANDLER(10);
|
||||||
|
REGISTER_ISR_HANDLER(11);
|
||||||
|
REGISTER_ISR_HANDLER(12);
|
||||||
|
REGISTER_ISR_HANDLER(13);
|
||||||
|
REGISTER_ISR_HANDLER(14);
|
||||||
|
REGISTER_ISR_HANDLER(15);
|
||||||
|
REGISTER_ISR_HANDLER(16);
|
||||||
|
REGISTER_ISR_HANDLER(17);
|
||||||
|
REGISTER_ISR_HANDLER(18);
|
||||||
|
REGISTER_ISR_HANDLER(19);
|
||||||
|
REGISTER_ISR_HANDLER(20);
|
||||||
|
REGISTER_ISR_HANDLER(21);
|
||||||
|
REGISTER_ISR_HANDLER(22);
|
||||||
|
REGISTER_ISR_HANDLER(23);
|
||||||
|
REGISTER_ISR_HANDLER(24);
|
||||||
|
REGISTER_ISR_HANDLER(25);
|
||||||
|
REGISTER_ISR_HANDLER(26);
|
||||||
|
REGISTER_ISR_HANDLER(27);
|
||||||
|
REGISTER_ISR_HANDLER(28);
|
||||||
|
REGISTER_ISR_HANDLER(29);
|
||||||
|
REGISTER_ISR_HANDLER(30);
|
||||||
|
REGISTER_ISR_HANDLER(31);
|
||||||
|
|
||||||
|
REGISTER_IRQ_HANDLER(0);
|
||||||
|
REGISTER_IRQ_HANDLER(1);
|
||||||
|
REGISTER_IRQ_HANDLER(2);
|
||||||
|
REGISTER_IRQ_HANDLER(3);
|
||||||
|
REGISTER_IRQ_HANDLER(4);
|
||||||
|
REGISTER_IRQ_HANDLER(5);
|
||||||
|
REGISTER_IRQ_HANDLER(6);
|
||||||
|
REGISTER_IRQ_HANDLER(7);
|
||||||
|
REGISTER_IRQ_HANDLER(8);
|
||||||
|
REGISTER_IRQ_HANDLER(9);
|
||||||
|
REGISTER_IRQ_HANDLER(10);
|
||||||
|
REGISTER_IRQ_HANDLER(11);
|
||||||
|
REGISTER_IRQ_HANDLER(12);
|
||||||
|
REGISTER_IRQ_HANDLER(13);
|
||||||
|
REGISTER_IRQ_HANDLER(14);
|
||||||
|
REGISTER_IRQ_HANDLER(15);
|
||||||
|
|
||||||
|
flush_idt();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,155 @@
|
||||||
|
#include <BAN/Errors.h>
|
||||||
|
#include <kernel/kmalloc.h>
|
||||||
|
#include <kernel/MMU.h>
|
||||||
|
|
||||||
|
#define PRESENT (1 << 0)
|
||||||
|
#define READ_WRITE (1 << 1)
|
||||||
|
|
||||||
|
#define PAGE_SIZE 0x1000
|
||||||
|
#define PAGE_MASK ~(PAGE_SIZE - 1)
|
||||||
|
|
||||||
|
#define CLEANUP_STRUCTURE(s) \
|
||||||
|
for (uint64_t i = 0; i < 512; i++) \
|
||||||
|
if (s[i] & PRESENT) \
|
||||||
|
goto cleanup_done; \
|
||||||
|
kfree(s)
|
||||||
|
|
||||||
|
static MMU* s_instance = nullptr;
|
||||||
|
|
||||||
|
void MMU::Intialize()
|
||||||
|
{
|
||||||
|
ASSERT(s_instance == nullptr);
|
||||||
|
s_instance = new MMU();
|
||||||
|
}
|
||||||
|
|
||||||
|
MMU& MMU::Get()
|
||||||
|
{
|
||||||
|
ASSERT(s_instance);
|
||||||
|
return *s_instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint64_t* allocate_page_aligned_page()
|
||||||
|
{
|
||||||
|
void* page = kmalloc(PAGE_SIZE, PAGE_SIZE);
|
||||||
|
ASSERT(page);
|
||||||
|
memset(page, 0, PAGE_SIZE);
|
||||||
|
return (uint64_t*)page;
|
||||||
|
}
|
||||||
|
|
||||||
|
MMU::MMU()
|
||||||
|
{
|
||||||
|
// Identity map from 4 KiB -> 4 MiB
|
||||||
|
m_highest_paging_struct = allocate_page_aligned_page();
|
||||||
|
|
||||||
|
uint64_t* pdpt = allocate_page_aligned_page();
|
||||||
|
m_highest_paging_struct[0] = (uint64_t)pdpt | READ_WRITE | PRESENT;
|
||||||
|
|
||||||
|
uint64_t* pd = allocate_page_aligned_page();
|
||||||
|
pdpt[0] = (uint64_t)pd | READ_WRITE | PRESENT;
|
||||||
|
|
||||||
|
for (uint32_t i = 0; i < 2; i++)
|
||||||
|
{
|
||||||
|
uint64_t* pt = allocate_page_aligned_page();
|
||||||
|
for (uint64_t j = 0; j < 512; j++)
|
||||||
|
pt[j] = (i << 21) | (j << 12) | READ_WRITE | PRESENT;
|
||||||
|
pd[i] = (uint64_t)pt | READ_WRITE | PRESENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unmap 0 -> 4 KiB
|
||||||
|
uint64_t* pt1 = (uint64_t*)(pd[0] & PAGE_MASK);
|
||||||
|
pt1[0] = 0;
|
||||||
|
|
||||||
|
// Load the new pml4
|
||||||
|
asm volatile("movq %0, %%cr3" :: "r"(m_highest_paging_struct));
|
||||||
|
}
|
||||||
|
|
||||||
|
void MMU::AllocatePage(uintptr_t address)
|
||||||
|
{
|
||||||
|
ASSERT((address >> 48) == 0);
|
||||||
|
|
||||||
|
address &= PAGE_MASK;
|
||||||
|
|
||||||
|
uint64_t pml4e = (address >> 39) & 0x1FF;
|
||||||
|
uint64_t pdpte = (address >> 30) & 0x1FF;
|
||||||
|
uint64_t pde = (address >> 21) & 0x1FF;
|
||||||
|
uint64_t pte = (address >> 12) & 0x1FF;
|
||||||
|
|
||||||
|
uint64_t* pml4 = m_highest_paging_struct;
|
||||||
|
if (!(pml4[pml4e] & PRESENT))
|
||||||
|
{
|
||||||
|
uint64_t* pdpt = allocate_page_aligned_page();
|
||||||
|
pml4[pml4e] = (uint64_t)pdpt | READ_WRITE | PRESENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t* pdpt = (uint64_t*)(pml4[pml4e] & PAGE_MASK);
|
||||||
|
if (!(pdpt[pdpte] & PRESENT))
|
||||||
|
{
|
||||||
|
uint64_t* pd = allocate_page_aligned_page();
|
||||||
|
pdpt[pdpte] = (uint64_t)pd | READ_WRITE | PRESENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t* pd = (uint64_t*)(pdpt[pdpte] & PAGE_MASK);
|
||||||
|
if (!(pd[pde] & PRESENT))
|
||||||
|
{
|
||||||
|
uint64_t* pt = allocate_page_aligned_page();
|
||||||
|
pd[pde] = (uint64_t)pt | READ_WRITE | PRESENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t* pt = (uint64_t*)(pd[pde] & PAGE_MASK);
|
||||||
|
if (!(pt[pte] & PRESENT))
|
||||||
|
pt[pte] = address | READ_WRITE | PRESENT;
|
||||||
|
|
||||||
|
asm volatile("invlpg (%0)" :: "r"(address) : "memory");
|
||||||
|
}
|
||||||
|
|
||||||
|
void MMU::AllocateRange(uintptr_t address, ptrdiff_t size)
|
||||||
|
{
|
||||||
|
uintptr_t s_page = address & PAGE_MASK;
|
||||||
|
uintptr_t e_page = (address + size - 1) & PAGE_MASK;
|
||||||
|
for (uintptr_t page = s_page; page <= e_page; page += PAGE_SIZE)
|
||||||
|
AllocatePage(page);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MMU::UnAllocatePage(uintptr_t address)
|
||||||
|
{
|
||||||
|
ASSERT((address >> 48) == 0);
|
||||||
|
|
||||||
|
address &= PAGE_MASK;
|
||||||
|
|
||||||
|
uint64_t pml4e = (address >> 39) & 0x1FF;
|
||||||
|
uint64_t pdpte = (address >> 30) & 0x1FF;
|
||||||
|
uint64_t pde = (address >> 21) & 0x1FF;
|
||||||
|
uint64_t pte = (address >> 12) & 0x1FF;
|
||||||
|
|
||||||
|
uint64_t* pml4 = m_highest_paging_struct;
|
||||||
|
ASSERT(pml4[pml4e] & PRESENT);
|
||||||
|
|
||||||
|
uint64_t* pdpt = (uint64_t*)(pml4[pml4e] & PAGE_MASK);
|
||||||
|
ASSERT(pdpt[pdpte] & PRESENT);
|
||||||
|
|
||||||
|
uint64_t* pd = (uint64_t*)(pdpt[pdpte] & PAGE_MASK);
|
||||||
|
ASSERT(pd[pde] & PRESENT);
|
||||||
|
|
||||||
|
uint64_t* pt = (uint64_t*)(pd[pde] & PAGE_MASK);
|
||||||
|
ASSERT(pt[pte] & PRESENT);
|
||||||
|
|
||||||
|
pt[pte] = 0;
|
||||||
|
|
||||||
|
CLEANUP_STRUCTURE(pt);
|
||||||
|
pd[pde] = 0;
|
||||||
|
CLEANUP_STRUCTURE(pd);
|
||||||
|
pdpt[pdpte] = 0;
|
||||||
|
CLEANUP_STRUCTURE(pdpt);
|
||||||
|
pml4[pml4e] = 0;
|
||||||
|
cleanup_done:
|
||||||
|
|
||||||
|
asm volatile("invlpg (%0)" :: "r"(address) : "memory");
|
||||||
|
}
|
||||||
|
|
||||||
|
void MMU::UnAllocateRange(uintptr_t address, ptrdiff_t size)
|
||||||
|
{
|
||||||
|
uintptr_t s_page = address & PAGE_MASK;
|
||||||
|
uintptr_t e_page = (address + size - 1) & PAGE_MASK;
|
||||||
|
for (uintptr_t page = s_page; page <= e_page; page += PAGE_SIZE)
|
||||||
|
UnAllocatePage(page);
|
||||||
|
}
|
|
@ -0,0 +1,199 @@
|
||||||
|
# Declare constants for the multiboot header
|
||||||
|
.set ALIGN, 1<<0 # align loaded modules on page boundaries
|
||||||
|
.set MEMINFO, 1<<1 # provide memory map
|
||||||
|
.set VIDEOINFO, 1<<2 # provide video info
|
||||||
|
.set MB_FLAGS, ALIGN | MEMINFO | VIDEOINFO # this is the Multiboot 'flag' field
|
||||||
|
.set MB_MAGIC, 0x1BADB002 # 'magic number' lets bootloader find the header
|
||||||
|
.set MB_CHECKSUM, -(MB_MAGIC + MB_FLAGS) #checksum of above, to prove we are multiboot
|
||||||
|
|
||||||
|
.set PG_PRESENT, 1<<0
|
||||||
|
.set PG_READ_WRITE, 1<<1
|
||||||
|
.set PG_PAGE_SIZE, 1<<7
|
||||||
|
|
||||||
|
.code32
|
||||||
|
|
||||||
|
# Multiboot header
|
||||||
|
.section .multiboot, "aw"
|
||||||
|
.align 4
|
||||||
|
.long MB_MAGIC
|
||||||
|
.long MB_FLAGS
|
||||||
|
.long MB_CHECKSUM
|
||||||
|
.skip 20
|
||||||
|
|
||||||
|
.long 0
|
||||||
|
.long 800
|
||||||
|
.long 600
|
||||||
|
.long 32
|
||||||
|
|
||||||
|
.section .bss, "aw", @nobits
|
||||||
|
# Create stack
|
||||||
|
stack_bottom:
|
||||||
|
.skip 16384
|
||||||
|
stack_top:
|
||||||
|
|
||||||
|
.global g_kernel_cmdline
|
||||||
|
g_kernel_cmdline:
|
||||||
|
.skip 4096
|
||||||
|
|
||||||
|
# Reserve memory for paging structures,
|
||||||
|
# we will identity map first 4 MiB
|
||||||
|
|
||||||
|
# 0 MiB -> 1 MiB: bootloader stuff
|
||||||
|
# 1 MiB -> 2 MiB: kernel
|
||||||
|
# 2 MiB -> 3 MiB: kmalloc
|
||||||
|
# 3 MiB -> 4 MiB: kmalloc_eternal
|
||||||
|
.align 4096
|
||||||
|
boot_pml4:
|
||||||
|
.skip 512 * 8
|
||||||
|
boot_pdpt1:
|
||||||
|
.skip 512 * 8
|
||||||
|
boot_pd1:
|
||||||
|
.skip 512 * 8
|
||||||
|
|
||||||
|
.section .text, "a"
|
||||||
|
|
||||||
|
.global g_multiboot_info
|
||||||
|
g_multiboot_info:
|
||||||
|
.skip 8
|
||||||
|
.global g_multiboot_magic
|
||||||
|
g_multiboot_magic:
|
||||||
|
.skip 8
|
||||||
|
|
||||||
|
boot_gdt:
|
||||||
|
.quad 0 // null
|
||||||
|
.quad (1<<53) | (1<<47) | (1<<44) | (1<<43) // kernel code P,S,E,L (present, code/data, executable, long mode)
|
||||||
|
boot_gdtr:
|
||||||
|
.short . - boot_gdt - 1
|
||||||
|
.quad boot_gdt
|
||||||
|
|
||||||
|
has_cpuid:
|
||||||
|
pushfl
|
||||||
|
pushfl
|
||||||
|
xorl $0x00200000, (%esp)
|
||||||
|
popfl
|
||||||
|
pushfl
|
||||||
|
popl %eax
|
||||||
|
xorl (%esp), %eax
|
||||||
|
popfl
|
||||||
|
testl $0x00200000, %eax
|
||||||
|
ret
|
||||||
|
|
||||||
|
is_64_bit:
|
||||||
|
movl $0x80000000, %eax
|
||||||
|
cpuid
|
||||||
|
cmpl $0x80000001, %eax
|
||||||
|
jl .no_extension
|
||||||
|
movl $0x80000001, %eax
|
||||||
|
cpuid
|
||||||
|
testl $(1 << 29), %edx
|
||||||
|
ret
|
||||||
|
.no_extension:
|
||||||
|
cmpl %eax, %eax
|
||||||
|
ret
|
||||||
|
|
||||||
|
check_requirements:
|
||||||
|
call has_cpuid
|
||||||
|
jz .exit
|
||||||
|
call is_64_bit
|
||||||
|
jz .exit
|
||||||
|
ret
|
||||||
|
.exit:
|
||||||
|
jmp system_halt
|
||||||
|
|
||||||
|
copy_kernel_commandline:
|
||||||
|
pushl %esi
|
||||||
|
pushl %edi
|
||||||
|
movl g_multiboot_info, %esi
|
||||||
|
addl $16, %esi
|
||||||
|
movl (%esi), %esi
|
||||||
|
movl $1024, %ecx
|
||||||
|
movl $g_kernel_cmdline, %edi
|
||||||
|
rep movsl
|
||||||
|
popl %edi
|
||||||
|
popl %esi
|
||||||
|
ret
|
||||||
|
|
||||||
|
enable_sse:
|
||||||
|
movl %cr0, %eax
|
||||||
|
andw $0xFFFB, %ax
|
||||||
|
orw $0x0002, %ax
|
||||||
|
movl %eax, %cr0
|
||||||
|
movl %cr4, %eax
|
||||||
|
orw $0x0600, %ax
|
||||||
|
movl %eax, %cr4
|
||||||
|
ret
|
||||||
|
|
||||||
|
initialize_paging:
|
||||||
|
# identity map first 4 MiB
|
||||||
|
movl $(0x00000000 + PG_PAGE_SIZE + PG_READ_WRITE + PG_PRESENT), boot_pd1 + 0
|
||||||
|
movl $(0x00200000 + PG_PAGE_SIZE + PG_READ_WRITE + PG_PRESENT), boot_pd1 + 8
|
||||||
|
|
||||||
|
# set pdpte1 and pml4e1
|
||||||
|
movl $(boot_pd1 + PG_READ_WRITE + PG_PRESENT), boot_pdpt1
|
||||||
|
movl $(boot_pdpt1 + PG_READ_WRITE + PG_PRESENT), boot_pml4
|
||||||
|
|
||||||
|
# enable PAE
|
||||||
|
movl %cr4, %ecx
|
||||||
|
orl $0x20, %ecx
|
||||||
|
movl %ecx, %cr4
|
||||||
|
|
||||||
|
# set long mode enable bit
|
||||||
|
movl $0x100, %eax
|
||||||
|
movl $0x000, %edx
|
||||||
|
movl $0xC0000080, %ecx
|
||||||
|
wrmsr
|
||||||
|
|
||||||
|
# set address of paging structures
|
||||||
|
movl $boot_pml4, %ecx
|
||||||
|
movl %ecx, %cr3
|
||||||
|
|
||||||
|
# enable paging
|
||||||
|
movl %cr0, %ecx
|
||||||
|
orl $0x80000000, %ecx
|
||||||
|
movl %ecx, %cr0
|
||||||
|
|
||||||
|
ret
|
||||||
|
|
||||||
|
.global _start
|
||||||
|
.type _start, @function
|
||||||
|
_start:
|
||||||
|
# Initialize stack and multiboot info
|
||||||
|
movl $stack_top, %esp
|
||||||
|
movl %eax, g_multiboot_magic
|
||||||
|
movl %ebx, g_multiboot_info
|
||||||
|
|
||||||
|
call copy_kernel_commandline
|
||||||
|
call check_requirements
|
||||||
|
call enable_sse
|
||||||
|
|
||||||
|
call initialize_paging
|
||||||
|
|
||||||
|
# flush gdt and jump to 64 bit
|
||||||
|
lgdt boot_gdtr
|
||||||
|
ljmpl $0x08, $long_mode
|
||||||
|
|
||||||
|
.code64
|
||||||
|
long_mode:
|
||||||
|
# clear segment registers
|
||||||
|
movw $0x00, %ax
|
||||||
|
movw %ax, %ss
|
||||||
|
movw %ax, %ds
|
||||||
|
movw %ax, %es
|
||||||
|
movw %ax, %fs
|
||||||
|
movw %ax, %gs
|
||||||
|
|
||||||
|
# call global constuctors
|
||||||
|
call _init
|
||||||
|
|
||||||
|
# call to the kernel itself (clear ebp for stacktrace)
|
||||||
|
xorq %rbp, %rbp
|
||||||
|
call kernel_main
|
||||||
|
|
||||||
|
# call global destructors
|
||||||
|
call _fini
|
||||||
|
|
||||||
|
system_halt:
|
||||||
|
xchgw %bx, %bx
|
||||||
|
cli
|
||||||
|
1: hlt
|
||||||
|
jmp 1b
|
|
@ -0,0 +1,16 @@
|
||||||
|
/* x86-64 crti.s */
|
||||||
|
.section .init
|
||||||
|
.global _init
|
||||||
|
.type _init, @function
|
||||||
|
_init:
|
||||||
|
pushq %rbp
|
||||||
|
movq %rsp, %rbp
|
||||||
|
/* gcc will nicely put the contents of crtbegin.o's .init section here. */
|
||||||
|
|
||||||
|
.section .fini
|
||||||
|
.global _fini
|
||||||
|
.type _fini, @function
|
||||||
|
_fini:
|
||||||
|
pushq %rbp
|
||||||
|
movq %rsp, %rbp
|
||||||
|
/* gcc will nicely put the contents of crtbegin.o's .fini section here. */
|
|
@ -0,0 +1,10 @@
|
||||||
|
/* x86-64 crtn.s */
|
||||||
|
.section .init
|
||||||
|
/* gcc will nicely put the contents of crtend.o's .init section here. */
|
||||||
|
popq %rbp
|
||||||
|
ret
|
||||||
|
|
||||||
|
.section .fini
|
||||||
|
/* gcc will nicely put the contents of crtend.o's .fini section here. */
|
||||||
|
popq %rbp
|
||||||
|
ret
|
|
@ -0,0 +1,128 @@
|
||||||
|
.macro pushaq
|
||||||
|
pushq %rax
|
||||||
|
pushq %rbx
|
||||||
|
pushq %rcx
|
||||||
|
pushq %rdx
|
||||||
|
pushq %rbp
|
||||||
|
pushq %rdi
|
||||||
|
pushq %rsi
|
||||||
|
pushq %r8
|
||||||
|
pushq %r9
|
||||||
|
pushq %r10
|
||||||
|
pushq %r11
|
||||||
|
pushq %r12
|
||||||
|
pushq %r13
|
||||||
|
pushq %r14
|
||||||
|
pushq %r15
|
||||||
|
.endm
|
||||||
|
|
||||||
|
.macro popaq
|
||||||
|
popq %r15
|
||||||
|
popq %r14
|
||||||
|
popq %r13
|
||||||
|
popq %r12
|
||||||
|
popq %r11
|
||||||
|
popq %r10
|
||||||
|
popq %r9
|
||||||
|
popq %r8
|
||||||
|
popq %rsi
|
||||||
|
popq %rdi
|
||||||
|
popq %rbp
|
||||||
|
popq %rdx
|
||||||
|
popq %rcx
|
||||||
|
popq %rbx
|
||||||
|
popq %rax
|
||||||
|
.endm
|
||||||
|
|
||||||
|
isr_stub:
|
||||||
|
pushaq
|
||||||
|
movq 120(%rsp), %rdi
|
||||||
|
movq 128(%rsp), %rsi
|
||||||
|
call cpp_isr_handler
|
||||||
|
popaq
|
||||||
|
addq $16, %rsp
|
||||||
|
iretq
|
||||||
|
|
||||||
|
irq_stub:
|
||||||
|
pushaq
|
||||||
|
movq 120(%rsp), %rdi
|
||||||
|
call cpp_irq_handler
|
||||||
|
popaq
|
||||||
|
addq $16, %rsp
|
||||||
|
iretq
|
||||||
|
|
||||||
|
.macro isr n
|
||||||
|
.global isr\n
|
||||||
|
isr\n:
|
||||||
|
cli
|
||||||
|
pushq $0
|
||||||
|
pushq $\n
|
||||||
|
jmp isr_stub
|
||||||
|
.endm
|
||||||
|
|
||||||
|
.macro isr_err n
|
||||||
|
.global isr\n
|
||||||
|
isr\n:
|
||||||
|
cli
|
||||||
|
pushq $\n
|
||||||
|
jmp isr_stub
|
||||||
|
.endm
|
||||||
|
|
||||||
|
.macro irq n
|
||||||
|
.global irq\n
|
||||||
|
irq\n:
|
||||||
|
cli
|
||||||
|
pushq $0
|
||||||
|
pushq $\n
|
||||||
|
jmp irq_stub
|
||||||
|
.endm
|
||||||
|
|
||||||
|
isr 0
|
||||||
|
isr 1
|
||||||
|
isr 2
|
||||||
|
isr 3
|
||||||
|
isr 4
|
||||||
|
isr 5
|
||||||
|
isr 6
|
||||||
|
isr 7
|
||||||
|
isr_err 8
|
||||||
|
isr 9
|
||||||
|
isr_err 10
|
||||||
|
isr_err 11
|
||||||
|
isr_err 12
|
||||||
|
isr_err 13
|
||||||
|
isr_err 14
|
||||||
|
isr 15
|
||||||
|
isr 16
|
||||||
|
isr_err 17
|
||||||
|
isr 18
|
||||||
|
isr 19
|
||||||
|
isr 20
|
||||||
|
isr 21
|
||||||
|
isr 22
|
||||||
|
isr 23
|
||||||
|
isr 24
|
||||||
|
isr 25
|
||||||
|
isr 26
|
||||||
|
isr 27
|
||||||
|
isr 28
|
||||||
|
isr 29
|
||||||
|
isr 30
|
||||||
|
isr 31
|
||||||
|
|
||||||
|
irq 0
|
||||||
|
irq 1
|
||||||
|
irq 2
|
||||||
|
irq 3
|
||||||
|
irq 4
|
||||||
|
irq 5
|
||||||
|
irq 6
|
||||||
|
irq 7
|
||||||
|
irq 8
|
||||||
|
irq 9
|
||||||
|
irq 10
|
||||||
|
irq 11
|
||||||
|
irq 12
|
||||||
|
irq 13
|
||||||
|
irq 14
|
||||||
|
irq 15
|
|
@ -0,0 +1,27 @@
|
||||||
|
ENTRY (_start)
|
||||||
|
|
||||||
|
SECTIONS
|
||||||
|
{
|
||||||
|
. = 0x00100000;
|
||||||
|
|
||||||
|
.text BLOCK(4K) : ALIGN(4K)
|
||||||
|
{
|
||||||
|
*(.multiboot)
|
||||||
|
*(.text)
|
||||||
|
}
|
||||||
|
.rodata BLOCK(4K) : ALIGN(4K)
|
||||||
|
{
|
||||||
|
*(.rodata)
|
||||||
|
}
|
||||||
|
.data BLOCK(4K) : ALIGN(4K)
|
||||||
|
{
|
||||||
|
*(.data)
|
||||||
|
}
|
||||||
|
.bss BLOCK(4K) : ALIGN(4K)
|
||||||
|
{
|
||||||
|
*(COMMON)
|
||||||
|
*(.bss)
|
||||||
|
}
|
||||||
|
|
||||||
|
g_kernel_end = .;
|
||||||
|
}
|
|
@ -0,0 +1,11 @@
|
||||||
|
KERNEL_ARCH_CFLAGS=-mcmodel=large -mno-red-zone -mno-mmx
|
||||||
|
KERNEL_ARCH_CPPFLAGS=
|
||||||
|
KERNEL_ARCH_LDFLAGS=-z max-page-size=4096
|
||||||
|
KERNEL_ARCH_LIBS=
|
||||||
|
|
||||||
|
KERNEL_ARCH_OBJS= \
|
||||||
|
$(ARCHDIR)/boot.o \
|
||||||
|
$(ARCHDIR)/IDT.o \
|
||||||
|
$(ARCHDIR)/MMU.o \
|
||||||
|
$(ARCHDIR)/interrupts.o \
|
||||||
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
ARCH_CFLAGS=
|
||||||
|
ARCH_CPPFLAGS=
|
||||||
|
KERNEL_ARCH_CFLAGS=
|
||||||
|
KERNEL_ARCH_CPPFLAGS=
|
||||||
|
|
||||||
|
ARCH_FREEOBJS=\
|
||||||
|
|
||||||
|
ARCH_HOSTEDOBJS=\
|
Loading…
Reference in New Issue