Compare commits

...

2 commits

Author SHA1 Message Date
trimill c8c8d009f6
debugger 2024-02-01 17:01:52 -05:00
trimill b5b904cfc9
follow the corn style guide 2024-02-01 17:01:20 -05:00
26 changed files with 577 additions and 219 deletions

View file

@ -7,7 +7,7 @@
size_t backtrace(void **dst, size_t len); size_t backtrace(void **dst, size_t len);
// same as backtrace but with specified instruction and base pointer // same as backtrace but with specified instruction and base pointer
size_t backtrace_ex(void **dst, size_t len, void* ip, void *bp); size_t backtrace_ex(void **dst, size_t len, void *ip, void *bp);
// Log a backtrace // Log a backtrace
void log_backtrace(); void log_backtrace();

View file

@ -92,25 +92,25 @@ int ctoi(char c);
* @param s - the string to convert * @param s - the string to convert
* @returns the number inside s or 0 on error * @returns the number inside s or 0 on error
*/ */
int atoi(const char* s); int atoi(const char *s);
/** /**
* Converts the initial portiion of the string pointed to by s to long. * Converts the initial portiion of the string pointed to by s to long.
* @param s - the string to convert * @param s - the string to convert
* @returns the number inside s or 0 on error * @returns the number inside s or 0 on error
*/ */
long int atol(const char* s); long int atol(const char *s);
/** /**
* Converts the initial portiion of the string pointed to by s to long long. * Converts the initial portiion of the string pointed to by s to long long.
* @param s - the string to convert * @param s - the string to convert
* @returns the number inside s or 0 on error * @returns the number inside s or 0 on error
*/ */
long long int atoll(const char* s); long long int atoll(const char *s);
/** /**
* Converts a integer to asci inside a string with a given radix (base). * Converts a integer to asci inside a string with a given radix (base).
* @param n - the number to conver * @param n - the number to convert
* @param buffer - the string buffer * @param buffer - the string buffer
* @param radix - the base to convert * @param radix - the base to convert
*/ */
@ -118,7 +118,7 @@ char *itoa(int n, char *buffer, int radix);
/** /**
* Converts a long to asci inside a string with a given radix (base). * Converts a long to asci inside a string with a given radix (base).
* @param n - the number to conver * @param n - the number to convert
* @param buffer - the string buffer * @param buffer - the string buffer
* @param radix - the base to convert * @param radix - the base to convert
*/ */
@ -134,7 +134,7 @@ char *lltoa(long long int n, char *buffer, int radix);
/** /**
* Converts a unsigned integer to asci inside a string with a given radix (base). * Converts a unsigned integer to asci inside a string with a given radix (base).
* @param n - the number to conver * @param n - the number to convert
* @param buffer - the string buffer * @param buffer - the string buffer
* @param radix - the base to convert * @param radix - the base to convert
*/ */
@ -142,7 +142,7 @@ char *utoa(unsigned int n, char *buffer, int radix);
/** /**
* Converts a unsigned long to asci inside a string with a given radix (base). * Converts a unsigned long to asci inside a string with a given radix (base).
* @param n - the number to conver * @param n - the number to convert
* @param buffer - the string buffer * @param buffer - the string buffer
* @param radix - the base to convert * @param radix - the base to convert
*/ */

View file

@ -7,46 +7,46 @@
/** /**
* Initalize system memory allocator * Initalize system memory allocator
*/ */
extern void memory_init(struct memory_map *map); void memory_init(struct memory_map *map);
/** /**
* Disabled cpu interupts to not interfere with * Disabled cpu interupts to not interfere with
* current memory allocations. * current memory allocations.
*/ */
extern void memory_lock(void); void memory_lock(void);
/** /**
* Reenabled cpu interupts * Reenabled cpu interupts
*/ */
extern void memory_unlock(void); void memory_unlock(void);
/** /**
* @returns how much memory the system has * @returns how much memory the system has
*/ */
extern uint64_t memory_total(void); uint64_t memory_total(void);
/** /**
* @returns how much memory is free * @returns how much memory is free
*/ */
extern uint64_t memory_free(void); uint64_t memory_free(void);
/** /**
* @returns how much memory is used * @returns how much memory is used
*/ */
extern uint64_t memory_used(void); uint64_t memory_used(void);
/** /**
* Allocates a single page in memory. * Allocates a single page in memory.
* @returns the page if allocated or NULL on failure * @returns the page if allocated or NULL on failure
*/ */
extern void *alloc_page(void); void *alloc_page(void);
/** /**
* Allocats count pages in memory * Allocats count pages in memory
* @param count - the number of continious pages to allocate * @param count - the number of continious pages to allocate
* @returns the pages if allocated or NULL on failure * @returns the pages if allocated or NULL on failure
*/ */
extern void *alloc_pages(int count); void *alloc_pages(int count);
/** /**
* Frees a signle page in memory. * Frees a signle page in memory.
@ -54,7 +54,7 @@ extern void *alloc_pages(int count);
* Freeing in the middle of a block is allowed. * Freeing in the middle of a block is allowed.
* @param page - the pointer to the page * @param page - the pointer to the page
*/ */
extern void free_page(void *page); void free_page(void *page);
// TODO: implement free_page // TODO: implement free_page
/** /**
@ -64,7 +64,7 @@ extern void free_page(void *page);
* free_pages will from *page to end of block allocated. * free_pages will from *page to end of block allocated.
* @param page - the pointer to the page * @param page - the pointer to the page
*/ */
extern void free_pages(void *page); void free_pages(void *page);
// TODO: implement freeing in middle of block // TODO: implement freeing in middle of block
/** /**
@ -76,21 +76,21 @@ extern void free_pages(void *page);
* @param writable - if this memory should be writable * @param writable - if this memory should be writable
* @param user - if this memory should be user writable * @param user - if this memory should be user writable
*/ */
extern void *mmap(void *addr, size_t len); void *mmap(void *addr, size_t len);
/** /**
* Unmaps mapped address from the mmap function * Unmaps mapped address from the mmap function
* @param addr - the address returned from mmap * @param addr - the address returned from mmap
* @param len - the length allocated * @param len - the length allocated
*/ */
extern void unmap(void *addr); void unmap(void *addr);
/** /**
* Allocates size_t bytes in memory * Allocates size_t bytes in memory
* @param size - the amount of bytes to allocate * @param size - the amount of bytes to allocate
* @retruns the address allocated or NULL on failure * @retruns the address allocated or NULL on failure
*/ */
extern void *kalloc(size_t size); void *kalloc(size_t size);
/** /**
* Reallocates a given allocated ptr to a new size of bytes in memory. * Reallocates a given allocated ptr to a new size of bytes in memory.
@ -99,10 +99,10 @@ extern void *kalloc(size_t size);
* @param size - the amount of bytes to set the pointer to * @param size - the amount of bytes to set the pointer to
* @returns the address allocated or NULL on failure * @returns the address allocated or NULL on failure
*/ */
extern void *krealloc(void *ptr, size_t size); void *krealloc(void *ptr, size_t size);
/** /**
* Frees a allocated pointer in memory * Frees a allocated pointer in memory
* @param ptr - the pointer to free * @param ptr - the pointer to free
*/ */
extern void kfree(void *ptr); void kfree(void *ptr);

View file

@ -8,23 +8,23 @@
* Allocates a single physical page in memory * Allocates a single physical page in memory
* @preturns the physical address of the page * @preturns the physical address of the page
*/ */
extern void *alloc_phys_page(void); void *alloc_phys_page(void);
/** /**
* Allocates count physical pages in memory * Allocates count physical pages in memory
* @returns the physical address of the first page * @returns the physical address of the first page
*/ */
extern void *alloc_phys_pages(int count); void *alloc_phys_pages(int count);
/** /**
* Frees a single physical page in memory * Frees a single physical page in memory
* @param ptr - the physical address of the page * @param ptr - the physical address of the page
*/ */
extern void free_phys_page(void *ptr); void free_phys_page(void *ptr);
/** /**
* Frees count physical pages in memory * Frees count physical pages in memory
* @param ptr - the physical address of the first page * @param ptr - the physical address of the first page
* @param count - the number of pages in the list * @param count - the number of pages in the list
*/ */
extern void free_phys_pages(void *ptr, int count); void free_phys_pages(void *ptr, int count);

View file

@ -4,6 +4,7 @@
#define _PANIC_STR2(x) #x #define _PANIC_STR2(x) #x
#define panic(msg) _panic_impl(_PANIC_STR(__LINE__), __FILE__, msg) #define panic(msg) _panic_impl(_PANIC_STR(__LINE__), __FILE__, msg)
#define kassert(val, msg) do { if (!(val)) { panic(msg); } } while(0)
_Noreturn void _panic_impl(char *line, char *file, char *msg); _Noreturn void _panic_impl(char *line, char *file, char *msg);

View file

@ -162,11 +162,11 @@ static bool checksum(uint8_t *data, size_t len) {
static int read_s5_addr(struct acpi_state *state) { static int read_s5_addr(struct acpi_state *state) {
uintptr_t ptr = state->fadt.dsdt; uintptr_t ptr = state->fadt.dsdt;
char *s5_addr = (void*) (ptr + 36); char *s5_addr = (void *) (ptr + 36);
int dsdt_len = *((int*) (ptr+1)) - 36; int dsdt_len = *((int *) (ptr+1)) - 36;
while (0 < dsdt_len--) { while (0 < dsdt_len--) {
if ( memcmp(s5_addr, "_S5_", 4) == 0) if (memcmp(s5_addr, "_S5_", 4) == 0)
break; break;
s5_addr++; s5_addr++;
} }

View file

@ -16,11 +16,11 @@ size_t backtrace(void **dst, size_t len) {
size_t backtrace_ex(void **dst, size_t len, void *ip, void *bp) { size_t backtrace_ex(void **dst, size_t len, void *ip, void *bp) {
struct stackframe *frame = bp; struct stackframe *frame = bp;
__asm__ volatile ("mov %%rbp, %0" : "=r"(frame)); __asm__ volatile ("mov %%rbp, %0" : "=r"(frame));
if(len > 0) { if (len > 0) {
dst[0] = ip; dst[0] = ip;
} }
size_t i; size_t i;
for(i = 1; frame && i < len; i++) { for (i = 1; frame && i < len; i++) {
dst[i] = frame->rip; dst[i] = frame->rip;
frame = frame->rbp; frame = frame->rbp;
} }
@ -42,7 +42,7 @@ void log_backtrace_ex(void *ip, void *bp) {
serial_out_str(" 0x"); serial_out_str(" 0x");
serial_out_str(buf); serial_out_str(buf);
serial_out_str("\n"); serial_out_str("\n");
while(frame) { while (frame) {
ultoa((size_t)frame->rip, buf, 16); ultoa((size_t)frame->rip, buf, 16);
serial_out_str(" 0x"); serial_out_str(" 0x");
serial_out_str(buf); serial_out_str(buf);

343
src/arch/amd64/debugger.c Normal file
View file

@ -0,0 +1,343 @@
#include <lib.h>
#include <stddef.h>
#include <serial.h>
#include <backtrace.h>
#include "debugger.h"
struct dr6 {
uint64_t b0 : 1,
b1 : 1,
b2 : 1,
b3 : 1,
: 7,
bld : 1,
: 1,
bd : 1,
bs : 1,
bt : 1,
rtm : 1,
: 47;
};
struct dr7 {
uint64_t l0 : 1,
g0 : 1,
l1 : 1,
g1 : 1,
l2 : 1,
g2 : 1,
l3 : 1,
g3 : 1,
: 8,
rw0 : 2,
len0 : 2,
rw1 : 2,
len1 : 2,
rw2 : 2,
len2 : 2,
rw3 : 2,
len3 : 2,
: 32;
};
struct rflags {
uint64_t cf : 1,
: 1,
pf : 1,
: 1,
af : 1,
: 1,
zf : 1,
sf : 1,
tf : 1,
if_ : 1,
df : 1,
of : 1,
iopl : 2,
nt : 1,
md : 1,
rf : 1,
vm : 1,
ac : 1,
vif : 1,
vip : 1,
id : 1,
: 42;
};
struct breakpoint {
uint64_t addr;
uint8_t len;
uint8_t rw;
uint8_t used;
uint8_t enable;
};
static size_t dbg_steps = 0;
static int dbg_continue = 0;
static struct breakpoint bkps[4] = {{0}, {0}, {0}, {0}};
static void dbg_putc(char c) {
serial_out(c);
}
static void dbg_puts(char *msg) {
serial_out_str(msg);
}
static char dbg_getc() {
return serial_in();
}
static void debugger_msg(int cause, struct dr6 dr6) {
char buf[24];
switch (cause) {
case DEBUG_INT3:
dbg_puts("dbg: reached int3");
break;
case DEBUG_FAULT:
dbg_puts("dbg: a fault occured");
break;
case DEBUG_DBG:
if (dr6.bs)
dbg_puts("dbg: finished steps");
else if (dr6.b0)
dbg_puts("dbg: reached breakpoint 0");
else if (dr6.b1)
dbg_puts("dbg: reached breakpoint 1");
else if (dr6.b2)
dbg_puts("dbg: reached breakpoint 2");
else if (dr6.b3)
dbg_puts("dbg: reached breakpoint 3");
}
if (dbg_steps > 0) {
ultoa(dbg_steps, buf, 10);
dbg_puts(" (");
dbg_puts(buf);
dbg_puts(" steps left)");
}
if (dbg_continue > 0) {
dbg_puts(" (paused continue)");
}
dbg_puts("\n");
}
static void debugger_print_reg(char *name, uint64_t val) {
char buf[24];
char *end;
dbg_puts(name);
dbg_puts(": 0x");
end = ultoa(val, buf, 16);
for (int i = 0; i < 16 - (end - buf); i++) {
dbg_putc('0');
}
dbg_puts(buf);
dbg_puts(" (");
end = ultoa(val, buf, 10);
dbg_puts(buf);
dbg_puts(")\n");
}
static void debugger_print_regs(struct isr_regs *state) {
debugger_print_reg("rax", state->rax);
debugger_print_reg("rbx", state->rbx);
debugger_print_reg("rcx", state->rcx);
debugger_print_reg("rdx", state->rdx);
debugger_print_reg("rsi", state->rsi);
debugger_print_reg("rdi", state->rdi);
debugger_print_reg("rsp", state->rsp);
debugger_print_reg("rbp", state->rbp);
debugger_print_reg("r8 ", state->r8 );
debugger_print_reg("r9 ", state->r9 );
debugger_print_reg("r10", state->r10);
debugger_print_reg("r11", state->r11);
debugger_print_reg("r12", state->r12);
debugger_print_reg("r13", state->r13);
debugger_print_reg("r14", state->r14);
debugger_print_reg("r15", state->r15);
dbg_puts("---\n");
debugger_print_reg("rip", state->rip);
dbg_puts("---\n");
debugger_print_reg("rflags", state->rflags);
struct rflags *rflags = (struct rflags *)state->rflags;
dbg_puts("rflags: ");
if(rflags->cf) dbg_puts("CF ");
if(rflags->pf) dbg_puts("PF ");
if(rflags->af) dbg_puts("AF ");
if(rflags->zf) dbg_puts("ZF ");
if(rflags->sf) dbg_puts("SF ");
if(rflags->tf) dbg_puts("TF ");
if(rflags->if_) dbg_puts("IF ");
if(rflags->df) dbg_puts("DF ");
if(rflags->of) dbg_puts("OF ");
if(rflags->iopl) dbg_puts("IOPL ");
if(rflags->nt) dbg_puts("NT ");
if(rflags->md) dbg_puts("MD ");
if(rflags->rf) dbg_puts("RF ");
if(rflags->vm) dbg_puts("VM ");
if(rflags->ac) dbg_puts("AC ");
if(rflags->vif) dbg_puts("VIF ");
if(rflags->vip) dbg_puts("VIP ");
if(rflags->id) dbg_puts("ID ");
dbg_putc('\n');
}
#define PROMPT_LEN 60
static int debugger_handle_bkp_cmd(char *buf) {
if (buf[0] == 'l') {
// list breakpoints
char buf[20];
for (int i = 0; i < 4; i++) {
dbg_puts("breakpoint ");
dbg_putc('0' + i);
dbg_puts(": ");
struct breakpoint bkp = bkps[i];
if(!bkp.used) {
dbg_puts("unset\n");
continue;
}
dbg_puts(" 0x");
ultoa(bkp.addr, buf, 16);
dbg_puts(buf);
dbg_puts(" len=");
switch (bkp.len) {
case 0x0: dbg_putc('1'); break;
case 0x1: dbg_putc('2'); break;
case 0x2: dbg_putc('8'); break;
case 0x3: dbg_putc('4'); break;
}
dbg_puts(" trigger=");
switch (bkp.rw) {
case 0x0: dbg_puts("x "); break;
case 0x1: dbg_puts("w "); break;
case 0x2: dbg_puts("io"); break;
case 0x3: dbg_puts("rw"); break;
}
dbg_puts(bkp.enable ? " enabled" : " disabled");
}
return 1;
} else if (buf[0] == 'd') {
// disable breakpoints
bkps[0].enable = 0;
bkps[1].enable = 0;
bkps[2].enable = 0;
bkps[3].enable = 0;
return 1;
} else if (buf[0] == 'c') {
// clear breakpoints
bkps[0].used = 0;
bkps[1].used = 0;
bkps[2].used = 0;
bkps[3].used = 0;
return 1;
} else if (buf[0] <= '0' && buf[0] >= '3') {
dbg_puts("invalid breakpoint command\n");
return 1;
}
// TODO set breakpoints
return 1;
}
static void debugger_load_bkps() {
struct dr7 dr7;
__asm__ volatile ("mov %%dr7, %0" : "=r"(dr7));
dr7.g0 = bkps[0].enable & bkps[0].used;
dr7.g1 = bkps[1].enable & bkps[0].used;
dr7.g2 = bkps[2].enable & bkps[0].used;
dr7.g3 = bkps[3].enable & bkps[0].used;
dr7.l0 = 0;
dr7.l1 = 0;
dr7.l2 = 0;
dr7.l3 = 0;
dr7.rw0 = bkps[0].rw;
dr7.rw1 = bkps[1].rw;
dr7.rw2 = bkps[2].rw;
dr7.rw3 = bkps[3].rw;
dr7.len0 = bkps[0].len;
dr7.len1 = bkps[1].len;
dr7.len2 = bkps[2].len;
dr7.len3 = bkps[3].len;
__asm__ volatile ("mov %0, %%dr7" : : "r"(dr7));
}
static int debugger_prompt(struct isr_regs *state) {
char buf[PROMPT_LEN];
char *p = buf;
dbg_puts("dbg> ");
while ((*p = dbg_getc()) != '\r' && p < buf + PROMPT_LEN - 1) {
dbg_putc(*p++);
}
dbg_putc('\n');
for(; p < buf + PROMPT_LEN; p++) {
*p = 0;
}
struct rflags *rflags = (struct rflags *)&state->rflags;
switch (buf[0]) {
case '\0': // nothing entered
return 1;
case 'h': // help
dbg_puts("see debugger.c for help information\n");
return 1;
case 'q': // quit
return 0;
case 'c': // continue
rflags->tf = 1;
dbg_continue = 1;
return 0;
case 'r': // print registers
debugger_print_regs(state);
return 1;
case 'k': // backtrace
log_backtrace_ex((void *)state->rip, (void *)state->rbp);
return 1;
case 's': // step (n)
rflags->tf = 1;
dbg_steps = atol(buf + 1) - 1;
if (dbg_steps < 0) dbg_steps = 0;
return 0;
case 'b': // breakpoints
{
int res = debugger_handle_bkp_cmd(buf+1);
debugger_load_bkps();
return res;
}
default:
dbg_puts("unknown command\n");
return 1;
}
}
void debugger(struct isr_regs *state, int cause) {
struct dr6 dr6;
__asm__ volatile ("mov %%dr6, %0" : "=r"(dr6));
if (dr6.b0 || dr6.b1 || dr6.b2 || dr6.b3) {
} else {
if (dr6.bs && dbg_steps > 0) {
dbg_steps--;
return;
}
if (dr6.bs && dbg_continue) {
return;
}
}
debugger_msg(cause, dr6);
dbg_steps = 0;
dbg_continue = 0;
struct rflags *rflags = (struct rflags *)&state->rflags;
rflags->tf = 0;
while (debugger_prompt(state));
}

View file

@ -0,0 +1,9 @@
#pragma once
#include "idt.h"
#define DEBUG_INT3 0x00
#define DEBUG_DBG 0x01
#define DEBUG_FAULT 0x02
void debugger(struct isr_regs *state, int cause);

View file

@ -11,9 +11,9 @@ extern idt_pic_eoi
push rbx push rbx
push rcx push rcx
push rdx push rdx
push rbp
push rdi
push rsi push rsi
push rdi
push rbp
push r8 push r8
push r9 push r9
push r10 push r10
@ -33,9 +33,9 @@ extern idt_pic_eoi
pop r10 pop r10
pop r9 pop r9
pop r8 pop r8
pop rsi
pop rdi
pop rbp pop rbp
pop rdi
pop rsi
pop rdx pop rdx
pop rcx pop rcx
pop rbx pop rbx
@ -51,8 +51,7 @@ isr_stub_%+%1:
cld cld
mov rdi, %1 ; exception number mov rdi, %1 ; exception number
mov rsi, 0 ; placeholder error code mov rsi, 0 ; placeholder error code
mov rdx, [rsp + 15 * 8] ; instruction pointer mov rdx, rsp ; top of stack
mov rcx, rbp ; base pointer for stack trace
call idt_exception_handler call idt_exception_handler
POPALL POPALL
iretq iretq
@ -64,15 +63,18 @@ isr_stub_%+%1:
%macro ISRExceptionCode 1 %macro ISRExceptionCode 1
align 8 align 8
isr_stub_%+%1: isr_stub_%+%1:
; retrieve the error code without corrupting registers
mov [isr_tmp], rax
pop rax
mov [isr_err_code], rax
mov rax, [isr_tmp]
PUSHALL PUSHALL
cld cld
mov rdi, %1 ; exception number mov rdi, %1 ; exception number
mov rsi, [rsp + 15 * 8] ; error code mov rsi, [isr_err_code] ; error code
mov rdx, [rsp + 16 * 8] ; instruction pointer mov rdx, rsp ; top of stack
mov rcx, rbp ; base pointer for stack trace
call idt_exception_handler call idt_exception_handler
POPALL POPALL
sub rsp, 8 ; discard error code
iretq iretq
%endmacro %endmacro
@ -188,6 +190,10 @@ PICGeneric 47 ; 15
%assign i i+1 %assign i i+1
%endrep %endrep
section .data
isr_tmp: dq 0
isr_err_code: dq 0
; isr stub table ; isr stub table
section .rodata section .rodata
bits 64 bits 64

View file

@ -1,10 +1,10 @@
#include <stdint.h> #include <stdint.h>
#include <stddef.h> #include <stddef.h>
#include <panic.h>
#include <lib.h> #include <lib.h>
#include <serial.h> #include <serial.h>
#include <panic.h>
#include "backtrace.h" #include "debugger.h"
#include "idt.h" #include "idt.h"
#include "pic.h" #include "pic.h"
@ -53,8 +53,8 @@ void idt_init(void) {
idtr.size = (uint16_t)sizeof(struct idt_entry) * IDT_SIZE - 1; idtr.size = (uint16_t)sizeof(struct idt_entry) * IDT_SIZE - 1;
// initialize idt // initialize idt
for(size_t vector = 0; vector < IDT_SIZE; vector++) { for (size_t vector = 0; vector < IDT_SIZE; vector++) {
struct idt_entry* entry = &idt[vector]; struct idt_entry *entry = &idt[vector];
uint64_t isr = (uint64_t)isr_stub_table[vector]; uint64_t isr = (uint64_t)isr_stub_table[vector];
// interrupts before 0x20 are for cpu exceptions // interrupts before 0x20 are for cpu exceptions
@ -108,7 +108,16 @@ char *EXCEPTIONS[] = {
"0x1F Reserved", "0x1F Reserved",
}; };
void idt_exception_handler(uint64_t exception, uint64_t code, void *rip, void *rbp) { void idt_exception_handler(uint64_t exception, uint64_t code, struct isr_regs *state) {
// breakpoint interrupt
if (exception == 0x03) {
debugger(state, DEBUG_INT3);
return;
} else if (exception == 0x01) {
debugger(state, DEBUG_DBG);
return;
}
// TODO don't just panic // TODO don't just panic
char buf[24]; char buf[24];
char msg[256] = "Exception "; char msg[256] = "Exception ";
@ -120,7 +129,7 @@ void idt_exception_handler(uint64_t exception, uint64_t code, void *rip, void *r
strcat(msg, buf); strcat(msg, buf);
// page faults store the offending address in cr2 // page faults store the offending address in cr2
if(exception == 0x0E) { if (exception == 0x0E) {
strcat(msg, "\nPage fault address: 0x"); strcat(msg, "\nPage fault address: 0x");
void *addr; void *addr;
__asm__ volatile ("mov %%cr2, %0" : "=r"(addr)); __asm__ volatile ("mov %%cr2, %0" : "=r"(addr));
@ -128,7 +137,7 @@ void idt_exception_handler(uint64_t exception, uint64_t code, void *rip, void *r
strcat(msg, buf); strcat(msg, buf);
} }
panic_interrupt(rip, rbp, msg); panic_interrupt((void *)state->rip, (void *)state->rbp, msg);
} }
void idt_pic_eoi(uint8_t exception) { void idt_pic_eoi(uint8_t exception) {

View file

@ -1,3 +1,29 @@
#pragma once #pragma once
#include <stdint.h>
struct isr_regs {
uint64_t r15;
uint64_t r14;
uint64_t r13;
uint64_t r12;
uint64_t r11;
uint64_t r10;
uint64_t r9;
uint64_t r8;
uint64_t rbp;
uint64_t rdi;
uint64_t rsi;
uint64_t rdx;
uint64_t rcx;
uint64_t rbx;
uint64_t rax;
uint64_t rip;
uint64_t cs;
uint64_t rflags;
uint64_t rsp;
uint64_t ss;
};
void idt_init(); void idt_init();

View file

@ -13,81 +13,73 @@
#define MBOOT_OLD_RSDP 14 #define MBOOT_OLD_RSDP 14
#define MBOOT_NEW_RSDP 15 #define MBOOT_NEW_RSDP 15
extern char symtab;
#define kaddr(addr) ((uintptr_t)(&addr))
typedef uint8_t mboot_uint8_t;
typedef uint16_t mboot_uint16_t;
typedef uint32_t mboot_uint32_t;
typedef uint64_t mboot_uint64_t;
struct mboot_info { struct mboot_info {
mboot_uint32_t total_size; uint32_t total_size;
mboot_uint32_t reserved; uint32_t reserved;
char tags[]; char tags[];
}; };
struct mboot_tag { struct mboot_tag {
mboot_uint32_t type; uint32_t type;
mboot_uint32_t size; uint32_t size;
char data[]; char data[];
}; };
struct mboot_tag_elf_sections { struct mboot_tag_elf_sections {
mboot_uint32_t type; uint32_t type;
mboot_uint32_t size; uint32_t size;
mboot_uint16_t num; uint16_t num;
mboot_uint16_t entsize; uint16_t entsize;
mboot_uint16_t shndx; uint16_t shndx;
mboot_uint16_t reserved; uint16_t reserved;
char sections[]; char sections[];
}; };
struct mboot_tag_elf_sections_entry { struct mboot_tag_elf_sections_entry {
mboot_uint32_t sh_name; uint32_t sh_name;
mboot_uint32_t sh_type; uint32_t sh_type;
mboot_uint64_t sh_flags; uint64_t sh_flags;
mboot_uint64_t sh_addr; uint64_t sh_addr;
mboot_uint64_t sh_offset; uint64_t sh_offset;
mboot_uint64_t sh_size; uint64_t sh_size;
mboot_uint32_t sh_link; uint32_t sh_link;
mboot_uint32_t sh_info; uint32_t sh_info;
mboot_uint64_t sh_addralign; uint64_t sh_addralign;
mboot_uint64_t sh_entsize; uint64_t sh_entsize;
}; };
struct mboot_mmap_entry { struct mboot_mmap_entry {
mboot_uint64_t addr; uint64_t addr;
mboot_uint64_t len; uint64_t len;
mboot_uint32_t type; uint32_t type;
mboot_uint32_t zero; uint32_t zero;
}; };
struct mboot_tag_mmap { struct mboot_tag_mmap {
mboot_uint32_t type; uint32_t type;
mboot_uint32_t size; uint32_t size;
mboot_uint32_t entry_size; uint32_t entry_size;
mboot_uint32_t entry_version; uint32_t entry_version;
struct mboot_mmap_entry entries[]; struct mboot_mmap_entry entries[];
}; };
struct mboot_tag_old_rsdp { struct mboot_tag_old_rsdp {
mboot_uint32_t type; uint32_t type;
mboot_uint32_t size; uint32_t size;
mboot_uint8_t rsdp[]; uint8_t rsdp[];
}; };
struct mboot_tag_new_rsdp { struct mboot_tag_new_rsdp {
mboot_uint32_t type; uint32_t type;
mboot_uint32_t size; uint32_t size;
mboot_uint8_t rsdp[]; uint8_t rsdp[];
}; };
struct mboot_tag_cmdline { struct mboot_tag_cmdline {
mboot_uint32_t type; uint32_t type;
mboot_uint32_t size; uint32_t size;
mboot_uint8_t cmdline[]; uint8_t cmdline[];
}; };
static void read_symbols( static void read_symbols(
@ -100,7 +92,7 @@ static void read_symbols(
// struct mboot_elf_section_header *section = // struct mboot_elf_section_header *section =
// (struct mboot_elf_section_header *) (layout->elf_section_headers); // (struct mboot_elf_section_header *) (layout->elf_section_headers);
// //
// for (mboot_uint32_t i = 0; i < layout->num; i++) { // for (uint32_t i = 0; i < layout->num; i++) {
// char buf[20]; // char buf[20];
// //
// ultoa(i, buf, 10); // ultoa(i, buf, 10);
@ -134,7 +126,7 @@ static void read_cmdline(
struct boot_info *shim_info, struct boot_info *shim_info,
struct mboot_tag_cmdline *cmdline struct mboot_tag_cmdline *cmdline
) { ) {
mboot_uint32_t size = cmdline->size - 8; uint32_t size = cmdline->size - 8;
if (size >= CMDLINE_MAX) if (size >= CMDLINE_MAX)
size = CMDLINE_MAX; // truncate :( size = CMDLINE_MAX; // truncate :(
memcpy(shim_info->cmdline, cmdline->cmdline, size); memcpy(shim_info->cmdline, cmdline->cmdline, size);

View file

@ -68,25 +68,18 @@ static struct pdpte *pdpt_mapped = (void *) (uintptr_t) 0x201000;
static struct pde *pd_mapped = (void *) (uintptr_t) 0x202000; static struct pde *pd_mapped = (void *) (uintptr_t) 0x202000;
static struct pte *pt_mapped = (void *) (uintptr_t) 0x203000; static struct pte *pt_mapped = (void *) (uintptr_t) 0x203000;
static inline void static inline void invlpg(void *addr) {
invlpg(void *addr)
{
__asm volatile("invlpg (%0)" ::"r" (addr) : "memory"); __asm volatile("invlpg (%0)" ::"r" (addr) : "memory");
} }
static void static void load_addr(void *phys_addr) {
load_addr(void *phys_addr)
{
static struct pte *pt = &paging_pt[4]; static struct pte *pt = &paging_pt[4];
pt->address = (uint64_t)phys_addr >> 12; pt->address = (uint64_t)phys_addr >> 12;
pt->flags = F_PRESENT | F_WRITEABLE; pt->flags = F_PRESENT | F_WRITEABLE;
invlpg(addr_mapped); invlpg(addr_mapped);
} }
static void static void load_pml4(void *phys) {
load_pml4(
void *phys
) {
static struct pte *pt = &paging_pt[0]; static struct pte *pt = &paging_pt[0];
if ((uint64_t)phys >> 12 == pt->address) if ((uint64_t)phys >> 12 == pt->address)
return; return;
@ -95,10 +88,7 @@ load_pml4(
invlpg(pml4_mapped); invlpg(pml4_mapped);
} }
static void static void load_pdpt(void *phys) {
load_pdpt(
void *phys
) {
static struct pte *pt = &paging_pt[1]; static struct pte *pt = &paging_pt[1];
if ((uint64_t)phys >> 12 == pt->address) if ((uint64_t)phys >> 12 == pt->address)
return; return;
@ -107,10 +97,7 @@ load_pdpt(
invlpg(pdpt_mapped); invlpg(pdpt_mapped);
} }
static void static void load_pd(void *phys) {
load_pd(
void *phys
) {
static struct pte *pt = &paging_pt[2]; static struct pte *pt = &paging_pt[2];
if ((uint64_t)phys >> 12 == pt->address) if ((uint64_t)phys >> 12 == pt->address)
return; return;
@ -119,10 +106,7 @@ load_pd(
invlpg(pdpt_mapped); invlpg(pdpt_mapped);
} }
static void static void load_pt(void *phys) {
load_pt(
void *phys
) {
static struct pte *pt = &paging_pt[3]; static struct pte *pt = &paging_pt[3];
if ((uint64_t)phys >> 12 == pt->address) if ((uint64_t)phys >> 12 == pt->address)
return; return;
@ -135,8 +119,7 @@ load_pt(
#define PAG_CANNOT_ALLOC 1 #define PAG_CANNOT_ALLOC 1
#define PAG_NOT_PRESENT 2 #define PAG_NOT_PRESENT 2
static int static int select_pdpt(
select_pdpt(
void *virt, void *virt,
unsigned int flags, unsigned int flags,
struct pml4e *root, struct pml4e *root,
@ -165,8 +148,7 @@ select_pdpt(
return PAG_SUCCESS; return PAG_SUCCESS;
} }
static int static int select_pd(
select_pd(
void *virt, void *virt,
unsigned int flags, unsigned int flags,
struct pdpte *pdpt, struct pdpte *pdpt,
@ -195,8 +177,7 @@ select_pd(
return PAG_SUCCESS; return PAG_SUCCESS;
} }
static int static int select_pt(
select_pt(
void *virt, void *virt,
unsigned int flags, unsigned int flags,
struct pde *pd, struct pde *pd,
@ -225,8 +206,7 @@ select_pt(
return PAG_SUCCESS; return PAG_SUCCESS;
} }
static void static void select_page(
select_page(
void *virt, void *virt,
struct pte *pt, struct pte *pt,
struct pte **res struct pte **res
@ -238,8 +218,7 @@ select_page(
return; return;
} }
static inline void static inline void try_unmap_pml4(void) {
try_unmap_pml4(void) {
for (int i = 0; i < 512; i++) { for (int i = 0; i < 512; i++) {
if (pml4_mapped[i].flags & F_PRESENT) if (pml4_mapped[i].flags & F_PRESENT)
return; return;
@ -252,8 +231,7 @@ try_unmap_pml4(void) {
} }
} }
static inline void static inline void try_unmap_pdpt(void) {
try_unmap_pdpt(void) {
for (int i = 0; i < 512; i++) { for (int i = 0; i < 512; i++) {
if (pdpt_mapped[i].flags & F_PRESENT) if (pdpt_mapped[i].flags & F_PRESENT)
return; return;
@ -267,8 +245,7 @@ try_unmap_pdpt(void) {
try_unmap_pml4(); try_unmap_pml4();
} }
static inline void static inline void try_unmap_pd(void) {
try_unmap_pd(void) {
for (int i = 0; i < 512; i++) { for (int i = 0; i < 512; i++) {
if (pd_mapped[i].flags & F_PRESENT) if (pd_mapped[i].flags & F_PRESENT)
return; return;
@ -282,8 +259,7 @@ try_unmap_pd(void) {
try_unmap_pdpt(); try_unmap_pdpt();
} }
static inline void static inline void try_unmap_pt(void) {
try_unmap_pt(void) {
for (int i = 0; i < 512; i++) { for (int i = 0; i < 512; i++) {
if (pt_mapped[i].flags & F_PRESENT) if (pt_mapped[i].flags & F_PRESENT)
return; return;
@ -297,12 +273,10 @@ try_unmap_pt(void) {
try_unmap_pd(); try_unmap_pd();
} }
static void static void unmap_page(
unmap_page(
struct pml4e *root, struct pml4e *root,
void *virt void *virt
) { ) {
struct pdpte *pdpt; struct pdpte *pdpt;
struct pde *pd; struct pde *pd;
struct pte *pt; struct pte *pt;
@ -331,13 +305,11 @@ unmap_page(
return; return;
} }
static void static void unmap_pages(
unmap_pages(
struct pml4e *root, struct pml4e *root,
void *virt_start, void *virt_start,
long page_count long page_count
) { ) {
uint64_t pml4_o = -1, uint64_t pml4_o = -1,
pdpt_o = -1, pdpt_o = -1,
pd_o = -1; pd_o = -1;
@ -397,14 +369,12 @@ unmap_pages(
return; return;
} }
static int static int map_page(
map_page(
struct pml4e *root, struct pml4e *root,
void *virt, void *virt,
void *phys, void *phys,
unsigned int flags unsigned int flags
) { ) {
struct pdpte *pdpt; struct pdpte *pdpt;
struct pde *pd; struct pde *pd;
struct pte *pt; struct pte *pt;
@ -430,15 +400,13 @@ map_page(
return 0; return 0;
} }
static int static int map_pages(
map_pages(
struct pml4e *root, struct pml4e *root,
void *virt_start, void *virt_start,
void *phys_start, void *phys_start,
unsigned int flags, unsigned int flags,
long page_count long page_count
) { ) {
uint64_t pml4_o = -1, uint64_t pml4_o = -1,
pdpt_o = -1, pdpt_o = -1,
pd_o = -1; pd_o = -1;
@ -502,7 +470,6 @@ failed:
} }
void paging_init(void) { void paging_init(void) {
kernel_pml4[0].flags = F_PRESENT | F_WRITEABLE; kernel_pml4[0].flags = F_PRESENT | F_WRITEABLE;
kernel_pml4[0].address = (uint64_t)(&kernel_pdpt_0) >> 12; kernel_pml4[0].address = (uint64_t)(&kernel_pdpt_0) >> 12;

View file

@ -53,7 +53,7 @@ void pic_remap(void) {
void pic_mask(int irq) { void pic_mask(int irq) {
uint16_t port; uint16_t port;
uint8_t mask; uint8_t mask;
if(irq < 8) { if (irq < 8) {
port = PIC1_DATA; port = PIC1_DATA;
} else { } else {
port = PIC2_DATA; port = PIC2_DATA;
@ -66,7 +66,7 @@ void pic_mask(int irq) {
void pic_unmask(int irq) { void pic_unmask(int irq) {
uint16_t port; uint16_t port;
uint8_t mask; uint8_t mask;
if(irq < 8) { if (irq < 8) {
port = PIC1_DATA; port = PIC1_DATA;
} else { } else {
irq -= 8; irq -= 8;
@ -82,7 +82,7 @@ void pic_disable(void) {
} }
void pic_eoi(int irq) { void pic_eoi(int irq) {
if(irq >= 8) { if (irq >= 8) {
outb(PIC2_COMMAND, PIC_EOI); outb(PIC2_COMMAND, PIC_EOI);
} }
outb(PIC1_COMMAND, PIC_EOI); outb(PIC1_COMMAND, PIC_EOI);

View file

@ -18,7 +18,7 @@ int serial_init(void) {
outb(PORT + 0, 0xAE); // test by sending 0xAE outb(PORT + 0, 0xAE); // test by sending 0xAE
uint8_t response = inb(PORT + 0); uint8_t response = inb(PORT + 0);
if(response != 0xAE) { if (response != 0xAE) {
// TODO panic here? // TODO panic here?
return -1; return -1;
} }
@ -30,18 +30,18 @@ int serial_init(void) {
uint8_t serial_in(void) { uint8_t serial_in(void) {
// wait for data to be available // wait for data to be available
while((inb(PORT + 5) & 0x01) == 0); while ((inb(PORT + 5) & 0x01) == 0);
return inb(PORT); return inb(PORT);
} }
void serial_out(uint8_t ch) { void serial_out(uint8_t ch) {
// wait for output to be free // wait for output to be free
while((inb(PORT + 5) & 0x20) == 0); while ((inb(PORT + 5) & 0x20) == 0);
outb(PORT, ch); outb(PORT, ch);
} }
void serial_out_str(const char *str) { void serial_out_str(const char *str) {
for(; *str != '\0'; str++) { for (; *str != '\0'; str++) {
serial_out(*str); serial_out(*str);
} }
} }

View file

@ -11,7 +11,7 @@
static struct boot_info boot_info; static struct boot_info boot_info;
void* amd64_shim(long mboot_magic, void *mboot_data_ptr) { void *amd64_shim(long mboot_magic, void *mboot_data_ptr) {
serial_init(); serial_init();
paging_init(); paging_init();
pic_remap(); pic_remap();

View file

@ -4,6 +4,7 @@
#include <serial.h> #include <serial.h>
#include <fb.h> #include <fb.h>
#include <shim.h> #include <shim.h>
#include <panic.h>
void kmain(struct boot_info *info) { void kmain(struct boot_info *info) {
memory_init(&info->map); memory_init(&info->map);
@ -12,8 +13,8 @@ void kmain(struct boot_info *info) {
kprintf("enterd kmain\n"); kprintf("enterd kmain\n");
*(char*)(0xB8000 + 0x144) = 'h'; *(char *)(0xB8000 + 0x144) = 'h';
*(char*)(0xB8000 + 0x146) = 'i'; *(char *)(0xB8000 + 0x146) = 'i';
while (1) { while (1) {
//kprintf("ret: 0x%p\n", kalloc(1024)); //kprintf("ret: 0x%p\n", kalloc(1024));

View file

@ -45,19 +45,21 @@ int strncmp(const char *restrict lhs, const char *restrict rhs, unsigned long n)
} }
char *strcpy(char *restrict dest, const char *restrict src) { char *strcpy(char *restrict dest, const char *restrict src) {
for(; (*dest = *src); dest++, src++); char *d = dest;
for (; (*d = *src); d++, src++);
return dest; return dest;
} }
char *strncpy(char *restrict dest, const char *restrict src, unsigned long n) { char *strncpy(char *restrict dest, const char *restrict src, unsigned long n) {
for(; (*dest = *src) && n; dest++, src++, n--); char *d = dest;
memset(dest, 0, n); for (; (*d = *src) && n; d++, src++, n--);
memset(d, 0, n);
return dest; return dest;
} }
size_t strlen(const char *str) { size_t strlen(const char *str) {
const char *p; const char *p;
for(p = str; *p != 0; p++) {} for (p = str; *p != 0; p++) {}
return p - str; return p - str;
} }
@ -86,8 +88,8 @@ int isdigit(int c) {
#define ATOX(name, type) \ #define ATOX(name, type) \
type name(const char* s) { \ type name(const char *s) { \
for(; isspace(*s); s++); \ for (; isspace(*s); s++); \
int neg = 0; \ int neg = 0; \
switch (*s) { \ switch (*s) { \
case '-': \ case '-': \
@ -111,7 +113,7 @@ ATOX(atol, long int)
ATOX(atoll, long long int) ATOX(atoll, long long int)
char itoc(int i) { char itoc(int i) {
if(i < 10) { if (i < 10) {
return '0' + i; return '0' + i;
} else { } else {
return 'a' + (i - 10); return 'a' + (i - 10);
@ -119,9 +121,9 @@ char itoc(int i) {
} }
int ctoi(char c) { int ctoi(char c) {
if(c < 'A') { if (c < 'A') {
return c - '0'; return c - '0';
} else if(c < 'a') { } else if (c < 'a') {
return c - 'A' + 10; return c - 'A' + 10;
} else { } else {
return c - 'a' + 10; return c - 'a' + 10;
@ -210,19 +212,20 @@ end:
if (n == 0) { \ if (n == 0) { \
buffer[0] = '0'; \ buffer[0] = '0'; \
buffer[1] = '\0'; \ buffer[1] = '\0'; \
return buffer; \ return buffer + 1; \
} \ } \
char *start = buffer; \ char *start = buffer; \
for (; n; n /= radix) { \ for (; n; n /= radix) { \
*buffer++ = itoc(n % radix); \ *buffer++ = itoc(n % radix); \
} \ } \
char *buf_end = buffer; \
*buffer-- = '\0'; \ *buffer-- = '\0'; \
while(buffer > start) { \ while (buffer > start) { \
char tmp = *start; \ char tmp = *start; \
*start++ = *buffer; \ *start++ = *buffer; \
*buffer-- = tmp; \ *buffer-- = tmp; \
} \ } \
return buffer; \ return buf_end; \
} }
UXTOA(int, utoa) UXTOA(int, utoa)
@ -230,11 +233,11 @@ UXTOA(long int, ultoa)
UXTOA(long long int, ulltoa) UXTOA(long long int, ulltoa)
#define XTOA(type, name) \ #define XTOA(type, name) \
char *name(type n, char* buffer, int radix) { \ char *name(type n, char *buffer, int radix) { \
if (n == 0) { \ if (n == 0) { \
buffer[0] = '0'; \ buffer[0] = '0'; \
buffer[1] = '\0'; \ buffer[1] = '\0'; \
return buffer; \ return buffer + 1; \
} \ } \
if (n < 0) { \ if (n < 0) { \
*buffer++ = '-'; \ *buffer++ = '-'; \
@ -244,13 +247,14 @@ UXTOA(long long int, ulltoa)
for (; n; n /= radix) { \ for (; n; n /= radix) { \
*buffer++ = itoc(n % radix); \ *buffer++ = itoc(n % radix); \
} \ } \
char *buf_end = buffer; \
*buffer-- = '\0'; \ *buffer-- = '\0'; \
while(buffer > start) { \ while (buffer > start) { \
char tmp = *start; \ char tmp = *start; \
*start++ = *buffer; \ *start++ = *buffer; \
*buffer-- = tmp; \ *buffer-- = tmp; \
} \ } \
return buffer; \ return buf_end; \
} }
XTOA(int, itoa) XTOA(int, itoa)
@ -260,7 +264,7 @@ XTOA(long long int, lltoa)
#define STRTOX(name, type) \ #define STRTOX(name, type) \
type name(const char *s, char **endptr, int radix) { \ type name(const char *s, char **endptr, int radix) { \
*endptr = NULL; \ *endptr = NULL; \
for(; isspace(*s); s++); \ for (; isspace(*s); s++); \
int neg = 0; \ int neg = 0; \
switch (*s) { \ switch (*s) { \
case '-': \ case '-': \
@ -283,9 +287,9 @@ XTOA(long long int, lltoa)
radix = 10; \ radix = 10; \
} \ } \
} \ } \
for (; *s == '0'; s++, *endptr = (void*) s); \ for (; *s == '0'; s++, *endptr = (void *) s); \
type num = 0; \ type num = 0; \
for (; isdigit(*s); s++, *endptr = (void*) s) { \ for (; isdigit(*s); s++, *endptr = (void *) s) { \
num *= radix; \ num *= radix; \
num += *s - '0'; \ num += *s - '0'; \
} \ } \

View file

@ -19,7 +19,7 @@ static const size_t header_len = sizeof(struct page_header);
static struct page_header *start_header = NULL; static struct page_header *start_header = NULL;
static struct page_header *end_header = NULL; static struct page_header *end_header = NULL;
struct page_header* get_header(void *ptr) { struct page_header *get_header(void *ptr) {
struct page_header *header = struct page_header *header =
(struct page_header *) ((uintptr_t) ptr - header_len); (struct page_header *) ((uintptr_t) ptr - header_len);

View file

@ -170,7 +170,7 @@ void memory_init(struct memory_map *map) {
segment_count = 0; segment_count = 0;
for(uint32_t i = 0; i < map->entry_count; i++) { for (uint32_t i = 0; i < map->entry_count; i++) {
struct memory_segment *segment = &map->entries[i]; struct memory_segment *segment = &map->entries[i];
if (segment_invalid(segment)) if (segment_invalid(segment))
@ -201,7 +201,7 @@ void memory_init(struct memory_map *map) {
struct memory_area *area = page_start; struct memory_area *area = page_start;
kprintf("MEMORY MAP\n"); kprintf("MEMORY MAP\n");
for(uint32_t i = 0; i < map->entry_count; i++) { for (uint32_t i = 0; i < map->entry_count; i++) {
struct memory_segment *segment = &map->entries[i]; struct memory_segment *segment = &map->entries[i];
if (segment_invalid(segment)) if (segment_invalid(segment))

View file

@ -118,7 +118,7 @@ void *virtaddr_alloc(int n_pages) {
} }
static void merge_back(struct addr_node *node) { static void merge_back(struct addr_node *node) {
while(node->prev && !node->is_alloc) { while (node->prev && !node->is_alloc) {
struct addr_node *temp = node->prev; struct addr_node *temp = node->prev;
node->start = node->prev->start; node->start = node->prev->start;
node->prev = node->prev->prev; node->prev = node->prev->prev;
@ -130,7 +130,7 @@ static void merge_back(struct addr_node *node) {
} }
static void merge_forward(struct addr_node *node) { static void merge_forward(struct addr_node *node) {
while(node->next && !node->is_alloc) { while (node->next && !node->is_alloc) {
struct addr_node *temp = node->next; struct addr_node *temp = node->next;
node->end = node->next->end; node->end = node->next->end;
node->next = node->next->next; node->next = node->next->next;