Style: harmonize formatting

Thanks to: "clang-format -i -style=file **/*.{c,h}"
This commit is contained in:
Mathieu Maret 2020-04-27 00:14:37 +02:00
parent fd6551e90c
commit 3b97d0307d
40 changed files with 1405 additions and 1458 deletions

View File

@ -18,208 +18,208 @@ static int formatPage(struct slabEntry *desc, size_t size, int selfContained);
int allocInit(void) int allocInit(void)
{ {
uint start = log2(sizeof(void *)); uint start = log2(sizeof(void *));
list_init(slub); list_init(slub);
int ret; int ret;
if ((ret = allocBookSlab(sizeof(struct slabDesc), 1))) { if ((ret = allocBookSlab(sizeof(struct slabDesc), 1))) {
pr_devel("Fail to allocBookSlab %d for slabDesc :( \n", ret); pr_devel("Fail to allocBookSlab %d for slabDesc :( \n", ret);
return ret; return ret;
}
if ((ret = allocBookSlab(sizeof(struct slabEntry), 1))) {
pr_devel("Fail to allocBookSlab %d for slabEntry :( \n", ret);
return ret;
}
for (uint i = start; i <= SLUB_SIZE; i++) {
if ((ret = allocBookSlab(1U << i, 0))) {
if (ret == -EEXIST)
continue;
pr_devel("Fail to allocBookSlab %d for %d \n", ret, (1U << i));
return ret;
} }
if ((ret = allocBookSlab(sizeof(struct slabEntry), 1))) { }
pr_devel("Fail to allocBookSlab %d for slabEntry :( \n", ret); return 0;
return ret;
}
for (uint i = start; i <= SLUB_SIZE; i++) {
if ((ret = allocBookSlab(1U << i, 0))) {
if(ret == -EEXIST)
continue;
pr_devel("Fail to allocBookSlab %d for %d \n", ret, (1U << i));
return ret;
}
}
return 0;
} }
int allocBookSlab(size_t size, int selfContained) int allocBookSlab(size_t size, int selfContained)
{ {
pr_devel("%s for size %d is self %d\n", __func__, size, selfContained); pr_devel("%s for size %d is self %d\n", __func__, size, selfContained);
struct slabDesc *slab = NULL; struct slabDesc *slab = NULL;
int slabIdx; int slabIdx;
int ret; int ret;
list_foreach(slub, slab, slabIdx) list_foreach(slub, slab, slabIdx)
{ {
if (slab->size == size) { if (slab->size == size) {
return -EEXIST; return -EEXIST;
}
if (slab->size > size) {
break;
}
} }
struct slabDesc *newSlab; if (slab->size > size) {
if ((ret = allocSlab(&newSlab, size, selfContained))) break;
return ret;
if (list_foreach_early_break(slub, slab, slabIdx)) {
list_insert_before(slub, slab, newSlab);
} else {
list_add_tail(slub, newSlab);
} }
return 0; }
struct slabDesc *newSlab;
if ((ret = allocSlab(&newSlab, size, selfContained)))
return ret;
if (list_foreach_early_break(slub, slab, slabIdx)) {
list_insert_before(slub, slab, newSlab);
} else {
list_add_tail(slub, newSlab);
}
return 0;
} }
int allocSlab(struct slabDesc **desc, size_t size, int selfContained) int allocSlab(struct slabDesc **desc, size_t size, int selfContained)
{ {
// pr_devel("%s for size %d is self %d\n", __func__, size, selfContained); // pr_devel("%s for size %d is self %d\n", __func__, size, selfContained);
if (size > PAGE_SIZE) if (size > PAGE_SIZE)
return -ENOENT; return -ENOENT;
paddr_t alloc = allocPhyPage(); paddr_t alloc = allocPhyPage();
if (alloc == (paddr_t)NULL) if (alloc == (paddr_t)NULL)
return -ENOMEM; return -ENOMEM;
if (pageMap((vaddr_t)alloc, alloc, PAGING_MEM_WRITE)) if (pageMap((vaddr_t)alloc, alloc, PAGING_MEM_WRITE))
return -ENOMEM; return -ENOMEM;
if (selfContained) { if (selfContained) {
*desc = (struct slabDesc *)alloc; *desc = (struct slabDesc *)alloc;
((*desc)->slab).freeEl = (char *)(*desc) + sizeof(struct slabDesc); ((*desc)->slab).freeEl = (char *)(*desc) + sizeof(struct slabDesc);
} else { } else {
*desc = malloc(sizeof(struct slabDesc)); *desc = malloc(sizeof(struct slabDesc));
(*desc)->slab.freeEl = (void *)alloc; (*desc)->slab.freeEl = (void *)alloc;
} }
struct slabEntry *slab = &(*desc)->slab; struct slabEntry *slab = &(*desc)->slab;
list_singleton(slab, slab); list_singleton(slab, slab);
slab->page = (vaddr_t)alloc; slab->page = (vaddr_t)alloc;
slab->full = 0; slab->full = 0;
(*desc)->size = size; (*desc)->size = size;
// pr_devel("got page %d for size %d first %d", alloc, size, (*desc)->slab.freeEl); // pr_devel("got page %d for size %d first %d", alloc, size, (*desc)->slab.freeEl);
return formatPage(&(*desc)->slab, size, selfContained); return formatPage(&(*desc)->slab, size, selfContained);
} }
int allocSlabEntry(struct slabEntry **desc, size_t size, int selfContained) int allocSlabEntry(struct slabEntry **desc, size_t size, int selfContained)
{ {
pr_devel("%s for size %d is self %d\n", __func__, size, selfContained); pr_devel("%s for size %d is self %d\n", __func__, size, selfContained);
if (size > PAGE_SIZE) if (size > PAGE_SIZE)
return -ENOENT; return -ENOENT;
paddr_t alloc = allocPhyPage(); paddr_t alloc = allocPhyPage();
if (alloc == (paddr_t)NULL) if (alloc == (paddr_t)NULL)
return -ENOMEM; return -ENOMEM;
if (pageMap((vaddr_t)alloc, alloc, PAGING_MEM_WRITE)) if (pageMap((vaddr_t)alloc, alloc, PAGING_MEM_WRITE))
return -ENOMEM; return -ENOMEM;
if (selfContained) { if (selfContained) {
*desc = (struct slabEntry *)alloc; *desc = (struct slabEntry *)alloc;
(*desc)->freeEl = (char *)(*desc) + sizeof(struct slabEntry); (*desc)->freeEl = (char *)(*desc) + sizeof(struct slabEntry);
} else { } else {
*desc = malloc(sizeof(struct slabEntry)); *desc = malloc(sizeof(struct slabEntry));
(*desc)->freeEl = (void *)alloc; (*desc)->freeEl = (void *)alloc;
} }
list_singleton(*desc, *desc); list_singleton(*desc, *desc);
(*desc)->page = (vaddr_t)alloc; (*desc)->page = (vaddr_t)alloc;
(*desc)->full = 0; (*desc)->full = 0;
// pr_devel("got page %d for size %d first %d", alloc, size, (*desc)->freeEl); // pr_devel("got page %d for size %d first %d", alloc, size, (*desc)->freeEl);
return formatPage((*desc), size, selfContained); return formatPage((*desc), size, selfContained);
} }
static int formatPage(struct slabEntry *desc, size_t size, int selfContained) static int formatPage(struct slabEntry *desc, size_t size, int selfContained)
{ {
char *cur = desc->freeEl; char *cur = desc->freeEl;
ulong nbEl = PAGE_SIZE / size - 1; ulong nbEl = PAGE_SIZE / size - 1;
if (selfContained) if (selfContained)
nbEl = (PAGE_SIZE - sizeof(struct slabDesc)) / size - 1; nbEl = (PAGE_SIZE - sizeof(struct slabDesc)) / size - 1;
ulong i; ulong i;
for (i = 0; i < nbEl; i++) { for (i = 0; i < nbEl; i++) {
*((vaddr_t *)cur) = (vaddr_t)cur + size; *((vaddr_t *)cur) = (vaddr_t)cur + size;
cur += size; cur += size;
} }
*((vaddr_t *)cur) = (vaddr_t)NULL; *((vaddr_t *)cur) = (vaddr_t)NULL;
// pr_devel("last at %d allocated %d\n", cur, i + 1); // pr_devel("last at %d allocated %d\n", cur, i + 1);
return 0; return 0;
} }
static void *allocFromSlab(struct slabEntry *slab) static void *allocFromSlab(struct slabEntry *slab)
{ {
vaddr_t *next = slab->freeEl; vaddr_t *next = slab->freeEl;
if (*next == (vaddr_t)NULL) { if (*next == (vaddr_t)NULL) {
pr_devel("Slab @%d is now full\n", slab); pr_devel("Slab @%d is now full\n", slab);
slab->full = 1; slab->full = 1;
} else { } else {
slab->freeEl = (void *)(*next); slab->freeEl = (void *)(*next);
} }
return (void *)next; return (void *)next;
} }
void *malloc(size_t size) void *malloc(size_t size)
{ {
if (size > (1U << SLUB_SIZE)) { if (size > (1U << SLUB_SIZE)) {
printf("implement malloc for big size\n"); printf("implement malloc for big size\n");
return NULL; return NULL;
} }
struct slabDesc *slab; struct slabDesc *slab;
uint slubIdx; uint slubIdx;
list_foreach(slub, slab, slubIdx) list_foreach(slub, slab, slubIdx)
{ {
if (size <= slab->size) if (size <= slab->size)
break; break;
} }
struct slabEntry *slabEntry; struct slabEntry *slabEntry;
int slabIdx; int slabIdx;
list_foreach(&slab->slab, slabEntry, slabIdx) list_foreach(&slab->slab, slabEntry, slabIdx)
{ {
if (!slabEntry->full) { if (!slabEntry->full) {
// pr_devel("found place in slub %d at idx %d for size %d\n", slubIdx, // pr_devel("found place in slub %d at idx %d for size %d\n", slubIdx,
// slabIdx, size); // slabIdx, size);
return allocFromSlab(slabEntry); return allocFromSlab(slabEntry);
}
} }
}
// No room found // No room found
struct slabEntry *newSlabEntry; struct slabEntry *newSlabEntry;
struct slabEntry *slabList = &slab->slab; struct slabEntry *slabList = &slab->slab;
int ret; int ret;
if ((ret = allocSlabEntry(&newSlabEntry, slab->size, IS_SELF_CONTAINED(&slab->slab)))) { if ((ret = allocSlabEntry(&newSlabEntry, slab->size, IS_SELF_CONTAINED(&slab->slab)))) {
pr_devel("Fail to allocSlabEntry %d\n", ret); pr_devel("Fail to allocSlabEntry %d\n", ret);
return NULL; return NULL;
} }
pr_devel("Allocate new slab for object of size %d\n", slab->size); pr_devel("Allocate new slab for object of size %d\n", slab->size);
list_add_tail(slabList, newSlabEntry); list_add_tail(slabList, newSlabEntry);
return allocFromSlab(newSlabEntry); return allocFromSlab(newSlabEntry);
} }
int freeFromSlab(void *ptr, struct slabEntry *slab) int freeFromSlab(void *ptr, struct slabEntry *slab)
{ {
struct slabEntry *slabEntry; struct slabEntry *slabEntry;
int slabIdx; int slabIdx;
list_foreach(slab, slabEntry, slabIdx) list_foreach(slab, slabEntry, slabIdx)
{ {
if ((slabEntry->page <= (vaddr_t)ptr) && if ((slabEntry->page <= (vaddr_t)ptr) &&
((vaddr_t)ptr < (slabEntry->page + PAGE_SIZE))) { ((vaddr_t)ptr < (slabEntry->page + PAGE_SIZE))) {
// pr_devel("free place! was %d is now %d\n", slabEntry->freeEl, ptr); // pr_devel("free place! was %d is now %d\n", slabEntry->freeEl, ptr);
if (slabEntry->full) { if (slabEntry->full) {
*((vaddr_t *)ptr) = (vaddr_t)NULL; *((vaddr_t *)ptr) = (vaddr_t)NULL;
} else { } else {
*((vaddr_t *)ptr) = (vaddr_t)slabEntry->freeEl; *((vaddr_t *)ptr) = (vaddr_t)slabEntry->freeEl;
} }
slabEntry->freeEl = ptr; slabEntry->freeEl = ptr;
slabEntry->full = 0; slabEntry->full = 0;
return 1; return 1;
}
} }
return 0; }
return 0;
} }
void free(void *ptr) void free(void *ptr)
{ {
if (!ptr) if (!ptr)
return; return;
struct slabDesc *slab; struct slabDesc *slab;
int slabIdx; int slabIdx;
list_foreach(slub, slab, slabIdx) list_foreach(slub, slab, slabIdx)
{
struct slabEntry *slabEntry;
int entryIdx;
list_foreach(&slab->slab, slabEntry, entryIdx)
{ {
struct slabEntry *slabEntry; if (freeFromSlab(ptr, slabEntry))
int entryIdx; return;
list_foreach(&slab->slab, slabEntry, entryIdx)
{
if (freeFromSlab(ptr, slabEntry))
return;
}
} }
pr_devel("free: slab not found\n"); }
pr_devel("free: slab not found\n");
} }

View File

@ -3,21 +3,21 @@
#include "stdarg.h" #include "stdarg.h"
struct slabEntry { struct slabEntry {
vaddr_t page; vaddr_t page;
void *freeEl; void *freeEl;
char full; char full;
struct slabEntry *next; struct slabEntry *next;
struct slabEntry *prev; struct slabEntry *prev;
}; };
struct slabDesc { struct slabDesc {
struct slabEntry slab; struct slabEntry slab;
size_t size; size_t size;
struct slabDesc *next; struct slabDesc *next;
struct slabDesc *prev; struct slabDesc *prev;
}; };
int allocInit(void); int allocInit(void);
int allocBookSlab(size_t size, int selfContained); int allocBookSlab(size_t size, int selfContained);
void *malloc(size_t size); void *malloc(size_t size);
void free(void* ptr); void free(void *ptr);

View File

@ -1,22 +1,24 @@
#pragma once #pragma once
#include "stack.h"
#include "klibc.h" #include "klibc.h"
#include "stack.h"
#define assert(p) do { \ #define assert(p) \
if (!(p)) { \ do { \
printf("BUG at %s:%d assert(%s)\n", \ if (!(p)) { \
__FILE__, __LINE__, #p); \ printf("BUG at %s:%d assert(%s)\n", __FILE__, __LINE__, #p); \
printStackTrace(5); \ printStackTrace(5); \
while(1){} \ while (1) { \
} \ } \
} while (0) } \
} while (0)
#define assertmsg(p, ...) do { \ #define assertmsg(p, ...) \
if (!(p)) { \ do { \
printf("BUG at %s:%d assert(%s)\n", \ if (!(p)) { \
__FILE__, __LINE__, #p); \ printf("BUG at %s:%d assert(%s)\n", __FILE__, __LINE__, #p); \
printf(__VA_ARGS__); \ printf(__VA_ARGS__); \
printStackTrace(5); \ printStackTrace(5); \
while(1){} \ while (1) { \
} \ } \
} while (0) } \
} while (0)

View File

@ -24,34 +24,34 @@
* irq_wrappers.S/exception_wrappers.S !!! Hence the constraint above. * irq_wrappers.S/exception_wrappers.S !!! Hence the constraint above.
*/ */
struct cpu_state { struct cpu_state {
/* (Lower addresses) */ /* (Lower addresses) */
/* These are Matos/SOS convention */ /* These are Matos/SOS convention */
uint16_t gs; uint16_t gs;
uint16_t fs; uint16_t fs;
uint16_t es; uint16_t es;
uint16_t ds; uint16_t ds;
uint16_t cpl0_ss; /* This is ALWAYS the Stack Segment of the uint16_t cpl0_ss; /* This is ALWAYS the Stack Segment of the
Kernel context (CPL0) of the interrupted Kernel context (CPL0) of the interrupted
thread, even for a user thread */ thread, even for a user thread */
uint16_t alignment_padding; /* unused */ uint16_t alignment_padding; /* unused */
uint32_t eax; uint32_t eax;
uint32_t ecx; uint32_t ecx;
uint32_t edx; uint32_t edx;
uint32_t ebx; uint32_t ebx;
uint32_t ebp; uint32_t ebp;
uint32_t esp; uint32_t esp;
uint32_t esi; uint32_t esi;
uint32_t edi; uint32_t edi;
/* MUST NEVER CHANGE (dependent on the IA32 iret instruction) */ /* MUST NEVER CHANGE (dependent on the IA32 iret instruction) */
uint32_t error_code; uint32_t error_code;
vaddr_t eip; vaddr_t eip;
uint32_t cs; /* 32bits according to the specs ! However, the CS uint32_t cs; /* 32bits according to the specs ! However, the CS
register is really 16bits long */ register is really 16bits long */
uint32_t eflags; uint32_t eflags;
/* (Higher addresses) */ /* (Higher addresses) */
} __attribute__((packed)); } __attribute__((packed));
/** /**
@ -73,7 +73,7 @@ struct cpu_state {
* Structure of an interrupted Kernel thread's context * Structure of an interrupted Kernel thread's context
*/ */
struct cpu_kstate { struct cpu_kstate {
struct cpu_state regs; struct cpu_state regs;
} __attribute__((packed)); } __attribute__((packed));
/** /**
@ -88,125 +88,125 @@ static void core_routine(cpu_kstate_function_arg1_t *start_func, void *start_arg
static void core_routine(cpu_kstate_function_arg1_t *start_func, void *start_arg, static void core_routine(cpu_kstate_function_arg1_t *start_func, void *start_arg,
cpu_kstate_function_arg1_t *exit_func, void *exit_arg) cpu_kstate_function_arg1_t *exit_func, void *exit_arg)
{ {
start_func(start_arg); start_func(start_arg);
exit_func(exit_arg); exit_func(exit_arg);
assert(!"The exit function of the thread should NOT return !"); assert(!"The exit function of the thread should NOT return !");
for (;;) for (;;)
; ;
} }
int cpu_kstate_init(struct cpu_state **ctxt, cpu_kstate_function_arg1_t *start_func, int cpu_kstate_init(struct cpu_state **ctxt, cpu_kstate_function_arg1_t *start_func,
vaddr_t start_arg, vaddr_t stack_bottom, size_t stack_size, vaddr_t start_arg, vaddr_t stack_bottom, size_t stack_size,
cpu_kstate_function_arg1_t *exit_func, vaddr_t exit_arg) cpu_kstate_function_arg1_t *exit_func, vaddr_t exit_arg)
{ {
/* We are initializing a Kernel thread's context */ /* We are initializing a Kernel thread's context */
struct cpu_kstate *kctxt; struct cpu_kstate *kctxt;
/* This is a critical internal function, so that it is assumed that /* This is a critical internal function, so that it is assumed that
the caller knows what he does: we legitimally assume that values the caller knows what he does: we legitimally assume that values
for ctxt, start_func, stack_* and exit_func are allways VALID ! */ for ctxt, start_func, stack_* and exit_func are allways VALID ! */
/* Setup the stack. /* Setup the stack.
* *
* On x86, the stack goes downward. Each frame is configured this * On x86, the stack goes downward. Each frame is configured this
* way (higher addresses first): * way (higher addresses first):
* *
* - (optional unused space. As of gcc 3.3, this space is 24 bytes) * - (optional unused space. As of gcc 3.3, this space is 24 bytes)
* - arg n * - arg n
* - arg n-1 * - arg n-1
* - ... * - ...
* - arg 1 * - arg 1
* - return instruction address: The address the function returns to * - return instruction address: The address the function returns to
* once finished * once finished
* - local variables * - local variables
* *
* The remaining of the code should be read from the end upward to * The remaining of the code should be read from the end upward to
* understand how the processor will handle it. * understand how the processor will handle it.
*/ */
vaddr_t tmp_vaddr = stack_bottom + stack_size; vaddr_t tmp_vaddr = stack_bottom + stack_size;
uint32_t *stack = (uint32_t *)tmp_vaddr; uint32_t *stack = (uint32_t *)tmp_vaddr;
/* If needed, poison the stack */ /* If needed, poison the stack */
#ifdef CPU_STATE_DETECT_UNINIT_KERNEL_VARS #ifdef CPU_STATE_DETECT_UNINIT_KERNEL_VARS
memset((void *)stack_bottom, CPU_STATE_STACK_POISON, stack_size); memset((void *)stack_bottom, CPU_STATE_STACK_POISON, stack_size);
#elif defined(CPU_STATE_DETECT_KERNEL_STACK_OVERFLOW) #elif defined(CPU_STATE_DETECT_KERNEL_STACK_OVERFLOW)
cpu_state_prepare_detect_kernel_stack_overflow(stack_bottom, stack_size); cpu_state_prepare_detect_kernel_stack_overflow(stack_bottom, stack_size);
#endif #endif
/* Simulate a call to the core_routine() function: prepare its /* Simulate a call to the core_routine() function: prepare its
arguments */ arguments */
*(--stack) = exit_arg; *(--stack) = exit_arg;
*(--stack) = (uint32_t)exit_func; *(--stack) = (uint32_t)exit_func;
*(--stack) = start_arg; *(--stack) = start_arg;
*(--stack) = (uint32_t)start_func; *(--stack) = (uint32_t)start_func;
*(--stack) = 0; /* Return address of core_routine => force page fault */ *(--stack) = 0; /* Return address of core_routine => force page fault */
/* /*
* Setup the initial context structure, so that the CPU will execute * Setup the initial context structure, so that the CPU will execute
* the function core_routine() once this new context has been * the function core_routine() once this new context has been
* restored on CPU * restored on CPU
*/ */
/* Compute the base address of the structure, which must be located /* Compute the base address of the structure, which must be located
below the previous elements */ below the previous elements */
tmp_vaddr = ((vaddr_t)stack) - sizeof(struct cpu_kstate); tmp_vaddr = ((vaddr_t)stack) - sizeof(struct cpu_kstate);
kctxt = (struct cpu_kstate *)tmp_vaddr; kctxt = (struct cpu_kstate *)tmp_vaddr;
/* Initialize the CPU context structure */ /* Initialize the CPU context structure */
memset(kctxt, 0x0, sizeof(struct cpu_kstate)); memset(kctxt, 0x0, sizeof(struct cpu_kstate));
/* Tell the CPU context structure that the first instruction to /* Tell the CPU context structure that the first instruction to
execute will be that of the core_routine() function */ execute will be that of the core_routine() function */
kctxt->regs.eip = (uint32_t)core_routine; kctxt->regs.eip = (uint32_t)core_routine;
/* Setup the segment registers */ /* Setup the segment registers */
kctxt->regs.cs = BUILD_SEGMENT_REG_VALUE(0, FALSE, SEG_KCODE); /* Code */ kctxt->regs.cs = BUILD_SEGMENT_REG_VALUE(0, FALSE, SEG_KCODE); /* Code */
kctxt->regs.ds = BUILD_SEGMENT_REG_VALUE(0, FALSE, SEG_KDATA); /* Data */ kctxt->regs.ds = BUILD_SEGMENT_REG_VALUE(0, FALSE, SEG_KDATA); /* Data */
kctxt->regs.es = BUILD_SEGMENT_REG_VALUE(0, FALSE, SEG_KDATA); /* Data */ kctxt->regs.es = BUILD_SEGMENT_REG_VALUE(0, FALSE, SEG_KDATA); /* Data */
kctxt->regs.cpl0_ss = BUILD_SEGMENT_REG_VALUE(0, FALSE, SEG_KDATA); /* Stack */ kctxt->regs.cpl0_ss = BUILD_SEGMENT_REG_VALUE(0, FALSE, SEG_KDATA); /* Stack */
/* fs and gs unused for the moment. */ /* fs and gs unused for the moment. */
/* The newly created context is initially interruptible */ /* The newly created context is initially interruptible */
kctxt->regs.eflags = (1 << 9); /* set IF bit */ kctxt->regs.eflags = (1 << 9); /* set IF bit */
/* Finally, update the generic kernel/user thread context */ /* Finally, update the generic kernel/user thread context */
*ctxt = (struct cpu_state *)kctxt; *ctxt = (struct cpu_state *)kctxt;
return 0; return 0;
} }
#if defined(CPU_STATE_DETECT_KERNEL_STACK_OVERFLOW) #if defined(CPU_STATE_DETECT_KERNEL_STACK_OVERFLOW)
void cpu_state_prepare_detect_kernel_stack_overflow(const struct cpu_state *ctxt, void cpu_state_prepare_detect_kernel_stack_overflow(const struct cpu_state *ctxt,
vaddr_t stack_bottom, size_t stack_size) vaddr_t stack_bottom, size_t stack_size)
{ {
(void)ctxt; (void)ctxt;
size_t poison_size = CPU_STATE_DETECT_KERNEL_STACK_OVERFLOW; size_t poison_size = CPU_STATE_DETECT_KERNEL_STACK_OVERFLOW;
if (poison_size > stack_size) if (poison_size > stack_size)
poison_size = stack_size; poison_size = stack_size;
memset((void *)stack_bottom, CPU_STATE_STACK_POISON, poison_size); memset((void *)stack_bottom, CPU_STATE_STACK_POISON, poison_size);
} }
void cpu_state_detect_kernel_stack_overflow(const struct cpu_state *ctxt, vaddr_t stack_bottom, void cpu_state_detect_kernel_stack_overflow(const struct cpu_state *ctxt, vaddr_t stack_bottom,
size_t stack_size) size_t stack_size)
{ {
unsigned char *c; unsigned char *c;
size_t i; size_t i;
/* On Matos/SOS, "ctxt" corresponds to the address of the esp register of /* On Matos/SOS, "ctxt" corresponds to the address of the esp register of
the saved context in Kernel mode (always, even for the interrupted the saved context in Kernel mode (always, even for the interrupted
context of a user thread). Here we make sure that this stack context of a user thread). Here we make sure that this stack
pointer is within the allowed stack area */ pointer is within the allowed stack area */
assert(((vaddr_t)ctxt) >= stack_bottom); assert(((vaddr_t)ctxt) >= stack_bottom);
assert(((vaddr_t)ctxt) + sizeof(struct cpu_kstate) <= stack_bottom + stack_size); assert(((vaddr_t)ctxt) + sizeof(struct cpu_kstate) <= stack_bottom + stack_size);
/* Check that the bottom of the stack has not been altered */ /* Check that the bottom of the stack has not been altered */
for (c = (unsigned char *)stack_bottom, i = 0; for (c = (unsigned char *)stack_bottom, i = 0;
(i < CPU_STATE_DETECT_KERNEL_STACK_OVERFLOW) && (i < stack_size); c++, i++) { (i < CPU_STATE_DETECT_KERNEL_STACK_OVERFLOW) && (i < stack_size); c++, i++) {
assert(CPU_STATE_STACK_POISON == *c); assert(CPU_STATE_STACK_POISON == *c);
} }
} }
#endif #endif
@ -216,26 +216,27 @@ void cpu_state_detect_kernel_stack_overflow(const struct cpu_state *ctxt, vaddr_
vaddr_t cpu_context_get_PC(const struct cpu_state *ctxt) vaddr_t cpu_context_get_PC(const struct cpu_state *ctxt)
{ {
assert(NULL != ctxt); assert(NULL != ctxt);
/* This is the PC of the interrupted context (ie kernel or user /* This is the PC of the interrupted context (ie kernel or user
context). */ context). */
return ctxt->eip; return ctxt->eip;
} }
vaddr_t cpu_context_get_SP(const struct cpu_state *ctxt) vaddr_t cpu_context_get_SP(const struct cpu_state *ctxt)
{ {
assert(NULL != ctxt); assert(NULL != ctxt);
/* On Matos/SOS, "ctxt" corresponds to the address of the esp register of /* On Matos/SOS, "ctxt" corresponds to the address of the esp register of
the saved context in Kernel mode (always, even for the interrupted the saved context in Kernel mode (always, even for the interrupted
context of a user thread). */ context of a user thread). */
return (vaddr_t)ctxt; return (vaddr_t)ctxt;
} }
void cpu_context_dump(const struct cpu_state *ctxt) void cpu_context_dump(const struct cpu_state *ctxt)
{ {
printf("CPU: eip=%x esp=%x eflags=%x cs=%x ds=%x ss=%x err=%x", (unsigned)ctxt->eip, printf("CPU: eip=%x esp=%x eflags=%x cs=%x ds=%x ss=%x err=%x", (unsigned)ctxt->eip,
(unsigned)ctxt, (unsigned)ctxt->eflags, (unsigned)GET_CPU_CS_REGISTER_VALUE(ctxt->cs), (unsigned)ctxt, (unsigned)ctxt->eflags,
(unsigned)ctxt->ds, (unsigned)ctxt->cpl0_ss, (unsigned)ctxt->error_code); (unsigned)GET_CPU_CS_REGISTER_VALUE(ctxt->cs), (unsigned)ctxt->ds,
(unsigned)ctxt->cpl0_ss, (unsigned)ctxt->error_code);
} }

View File

@ -5,16 +5,16 @@
modify it under the terms of the GNU General Public License modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2 as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version. of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
USA. USA.
*/ */
#pragma once #pragma once
@ -25,10 +25,9 @@
* be some kind of architecture-independent. * be some kind of architecture-independent.
*/ */
#include "errno.h"
#include "stdarg.h" #include "stdarg.h"
#include "types.h" #include "types.h"
#include "errno.h"
/** /**
* Opaque structure storing the CPU context of an inactive kernel or * Opaque structure storing the CPU context of an inactive kernel or
@ -41,13 +40,11 @@
*/ */
struct cpu_state; struct cpu_state;
/** /**
* The type of the functions passed as arguments to the Kernel thread * The type of the functions passed as arguments to the Kernel thread
* related functions. * related functions.
*/ */
typedef void (cpu_kstate_function_arg1_t(void * arg1)); typedef void(cpu_kstate_function_arg1_t(void *arg1));
/** /**
* Function to create an initial context for a kernel thread starting * Function to create an initial context for a kernel thread starting
@ -83,14 +80,9 @@ typedef void (cpu_kstate_function_arg1_t(void * arg1));
* *
* @note the newly created context is INTERRUPTIBLE by default ! * @note the newly created context is INTERRUPTIBLE by default !
*/ */
int cpu_kstate_init(struct cpu_state **kctxt, int cpu_kstate_init(struct cpu_state **kctxt, cpu_kstate_function_arg1_t *start_func,
cpu_kstate_function_arg1_t *start_func, vaddr_t start_arg, vaddr_t stack_bottom, size_t stack_size,
vaddr_t start_arg, cpu_kstate_function_arg1_t *exit_func, vaddr_t exit_arg);
vaddr_t stack_bottom,
size_t stack_size,
cpu_kstate_function_arg1_t *exit_func,
vaddr_t exit_arg);
/** /**
* Function that performs an immediate context-switch from one * Function that performs an immediate context-switch from one
@ -103,9 +95,7 @@ int cpu_kstate_init(struct cpu_state **kctxt,
* @param to_ctxt The CPU will resume its execution with the struct * @param to_ctxt The CPU will resume its execution with the struct
* cpu_state located at this address. Must NOT be NULL. * cpu_state located at this address. Must NOT be NULL.
*/ */
void cpu_context_switch(struct cpu_state **from_ctxt, void cpu_context_switch(struct cpu_state **from_ctxt, struct cpu_state *to_ctxt);
struct cpu_state *to_ctxt);
/* /*
* Switch to the new given context (of a kernel/user thread) without * Switch to the new given context (of a kernel/user thread) without
@ -121,52 +111,43 @@ void cpu_context_switch(struct cpu_state **from_ctxt,
* called after having changed the stack, but before restoring the CPU * called after having changed the stack, but before restoring the CPU
* context to switch_to_ctxt. * context to switch_to_ctxt.
*/ */
void void cpu_context_exit_to(struct cpu_state *switch_to_ctxt,
cpu_context_exit_to(struct cpu_state *switch_to_ctxt, cpu_kstate_function_arg1_t *reclaiming_func, uint32_t reclaiming_arg)
cpu_kstate_function_arg1_t *reclaiming_func, __attribute__((noreturn));
uint32_t reclaiming_arg) __attribute__((noreturn));
/* ======================================================================= /* =======================================================================
* Public Accessor functions * Public Accessor functions
*/ */
/** /**
* Return Program Counter stored in the saved kernel/user context * Return Program Counter stored in the saved kernel/user context
*/ */
vaddr_t cpu_context_get_PC(const struct cpu_state *ctxt); vaddr_t cpu_context_get_PC(const struct cpu_state *ctxt);
/** /**
* Return Stack Pointer stored in the saved kernel/user context * Return Stack Pointer stored in the saved kernel/user context
*/ */
vaddr_t cpu_context_get_SP(const struct cpu_state *ctxt); vaddr_t cpu_context_get_SP(const struct cpu_state *ctxt);
/** /**
* Dump the contents of the CPU context (bochs + x86_videomem) * Dump the contents of the CPU context (bochs + x86_videomem)
*/ */
void cpu_context_dump(const struct cpu_state *ctxt); void cpu_context_dump(const struct cpu_state *ctxt);
/* ======================================================================= /* =======================================================================
* Public Accessor functions TO BE USED ONLY BY Exception handlers * Public Accessor functions TO BE USED ONLY BY Exception handlers
*/ */
/** /**
* Return the argument passed by the CPU upon exception, as stored in the * Return the argument passed by the CPU upon exception, as stored in the
* saved context * saved context
*/ */
uint32_t cpu_context_get_EX_info(const struct cpu_state *ctxt); uint32_t cpu_context_get_EX_info(const struct cpu_state *ctxt);
/** /**
* Return the faulting address of the exception * Return the faulting address of the exception
*/ */
vaddr_t vaddr_t cpu_context_get_EX_faulting_vaddr(const struct cpu_state *ctxt);
cpu_context_get_EX_faulting_vaddr(const struct cpu_state *ctxt);
/* ======================================================================= /* =======================================================================
* Macros controlling stack poisoning. * Macros controlling stack poisoning.
@ -189,20 +170,18 @@ cpu_context_get_EX_faulting_vaddr(const struct cpu_state *ctxt);
* probable stack overflow. Its value indicates the number of bytes * probable stack overflow. Its value indicates the number of bytes
* used for this detection. * used for this detection.
*/ */
#define CPU_STATE_DETECT_KERNEL_STACK_OVERFLOW 64 #define CPU_STATE_DETECT_KERNEL_STACK_OVERFLOW 64
/* #undef CPU_STATE_DETECT_KERNEL_STACK_OVERFLOW */ /* #undef CPU_STATE_DETECT_KERNEL_STACK_OVERFLOW */
#if defined(CPU_STATE_DETECT_KERNEL_STACK_OVERFLOW) #if defined(CPU_STATE_DETECT_KERNEL_STACK_OVERFLOW)
void void cpu_state_prepare_detect_kernel_stack_overflow(const struct cpu_state *ctxt,
cpu_state_prepare_detect_kernel_stack_overflow(const struct cpu_state *ctxt, vaddr_t kernel_stack_bottom,
vaddr_t kernel_stack_bottom, size_t kernel_stack_size);
size_t kernel_stack_size);
void cpu_state_detect_kernel_stack_overflow(const struct cpu_state *ctxt, void cpu_state_detect_kernel_stack_overflow(const struct cpu_state *ctxt,
vaddr_t kernel_stack_bottom, vaddr_t kernel_stack_bottom,
size_t kernel_stack_size); size_t kernel_stack_size);
#else #else
# define cpu_state_prepare_detect_kernel_stack_overflow(ctxt,stkbottom,stksize) \ #define cpu_state_prepare_detect_kernel_stack_overflow(ctxt, stkbottom, stksize) ({/* nop \
({ /* nop */ }) */})
# define cpu_state_detect_kernel_stack_overflow(ctxt,stkbottom,stksize) \ #define cpu_state_detect_kernel_stack_overflow(ctxt, stkbottom, stksize) ({/* nop */})
({ /* nop */ })
#endif #endif

View File

@ -1,37 +1,36 @@
#pragma once #pragma once
#define EPERM 1 /* Operation not permitted */ #define EPERM 1 /* Operation not permitted */
#define ENOENT 2 /* No such file or directory */ #define ENOENT 2 /* No such file or directory */
#define ESRCH 3 /* No such process */ #define ESRCH 3 /* No such process */
#define EINTR 4 /* Interrupted system call */ #define EINTR 4 /* Interrupted system call */
#define EIO 5 /* I/O error */ #define EIO 5 /* I/O error */
#define ENXIO 6 /* No such device or address */ #define ENXIO 6 /* No such device or address */
#define E2BIG 7 /* Argument list too long */ #define E2BIG 7 /* Argument list too long */
#define ENOEXEC 8 /* Exec format error */ #define ENOEXEC 8 /* Exec format error */
#define EBADF 9 /* Bad file number */ #define EBADF 9 /* Bad file number */
#define ECHILD 10 /* No child processes */ #define ECHILD 10 /* No child processes */
#define EAGAIN 11 /* Try again */ #define EAGAIN 11 /* Try again */
#define ENOMEM 12 /* Out of memory */ #define ENOMEM 12 /* Out of memory */
#define EACCES 13 /* Permission denied */ #define EACCES 13 /* Permission denied */
#define EFAULT 14 /* Bad address */ #define EFAULT 14 /* Bad address */
#define ENOTBLK 15 /* Block device required */ #define ENOTBLK 15 /* Block device required */
#define EBUSY 16 /* Device or resource busy */ #define EBUSY 16 /* Device or resource busy */
#define EEXIST 17 /* File exists */ #define EEXIST 17 /* File exists */
#define EXDEV 18 /* Cross-device link */ #define EXDEV 18 /* Cross-device link */
#define ENODEV 19 /* No such device */ #define ENODEV 19 /* No such device */
#define ENOTDIR 20 /* Not a directory */ #define ENOTDIR 20 /* Not a directory */
#define EISDIR 21 /* Is a directory */ #define EISDIR 21 /* Is a directory */
#define EINVAL 22 /* Invalid argument */ #define EINVAL 22 /* Invalid argument */
#define ENFILE 23 /* File table overflow */ #define ENFILE 23 /* File table overflow */
#define EMFILE 24 /* Too many open files */ #define EMFILE 24 /* Too many open files */
#define ENOTTY 25 /* Not a typewriter */ #define ENOTTY 25 /* Not a typewriter */
#define ETXTBSY 26 /* Text file busy */ #define ETXTBSY 26 /* Text file busy */
#define EFBIG 27 /* File too large */ #define EFBIG 27 /* File too large */
#define ENOSPC 28 /* No space left on device */ #define ENOSPC 28 /* No space left on device */
#define ESPIPE 29 /* Illegal seek */ #define ESPIPE 29 /* Illegal seek */
#define EROFS 30 /* Read-only file system */ #define EROFS 30 /* Read-only file system */
#define EMLINK 31 /* Too many links */ #define EMLINK 31 /* Too many links */
#define EPIPE 32 /* Broken pipe */ #define EPIPE 32 /* Broken pipe */
#define EDOM 33 /* Math argument out of domain of func */ #define EDOM 33 /* Math argument out of domain of func */
#define ERANGE 34 /* Math result not representable */ #define ERANGE 34 /* Math result not representable */

View File

@ -9,16 +9,15 @@ exception_handler exception_handler_array[EXCEPTION_NUM] = {
int exceptionSetRoutine(int exception, exception_handler handler) int exceptionSetRoutine(int exception, exception_handler handler)
{ {
uint32_t flags; uint32_t flags;
if ((exception < 0) || exception >= EXCEPTION_NUM) if ((exception < 0) || exception >= EXCEPTION_NUM)
return -1; return -1;
disable_IRQs(flags); disable_IRQs(flags);
exception_handler_array[exception] = handler; exception_handler_array[exception] = handler;
idt_set_handler(EXCEPTION_INTERRUPT_BASE_ADDRESS + exception, (unsigned int)handler, idt_set_handler(EXCEPTION_INTERRUPT_BASE_ADDRESS + exception, (unsigned int)handler, 0);
0); restore_IRQs(flags);
restore_IRQs(flags); return 0;
return 0;
} }

View File

@ -41,6 +41,5 @@
#define EXCEPTION_NUM 32 #define EXCEPTION_NUM 32
typedef void (*exception_handler) (struct interrupt_frame *frame, ulong error_code); typedef void (*exception_handler)(struct interrupt_frame *frame, ulong error_code);
int exceptionSetRoutine(int exception, exception_handler handler); int exceptionSetRoutine(int exception, exception_handler handler);

View File

@ -6,16 +6,16 @@
// Need GCC > 6 // Need GCC > 6
#define DEFINE_INTERRUPT(int_nb) \ #define DEFINE_INTERRUPT(int_nb) \
__attribute__((interrupt)) void print_handler_##int_nb(struct interrupt_frame *frame, \ __attribute__((interrupt)) void print_handler_##int_nb(struct interrupt_frame *frame, \
ulong error_code) \ ulong error_code) \
{ \ { \
int intNbInt = int_nb; \ int intNbInt = int_nb; \
printStringDetails("EXCEPTION ", RED, BLACK, 0, VGA_HEIGHT - 1); \ printStringDetails("EXCEPTION ", RED, BLACK, 0, VGA_HEIGHT - 1); \
printIntDetails(intNbInt, RED, BLACK, 11, VGA_HEIGHT - 1); \ printIntDetails(intNbInt, RED, BLACK, 11, VGA_HEIGHT - 1); \
printIntDetails(error_code, RED, BLACK, 14, VGA_HEIGHT - 1); \ printIntDetails(error_code, RED, BLACK, 14, VGA_HEIGHT - 1); \
printf("Exception %d (Err %d) at 0x%x\n", int_nb, error_code, frame->eip); \ printf("Exception %d (Err %d) at 0x%x\n", int_nb, error_code, frame->eip); \
asm("hlt"); \ asm("hlt"); \
} }
DEFINE_INTERRUPT(EXCEPTION_DOUBLE_FAULT) DEFINE_INTERRUPT(EXCEPTION_DOUBLE_FAULT)
DEFINE_INTERRUPT(EXCEPTION_DIVIDE_ZERO) DEFINE_INTERRUPT(EXCEPTION_DIVIDE_ZERO)
@ -56,14 +56,14 @@ DEFINE_INTERRUPT(EXCEPTION_RESERVED_11)
__attribute__((interrupt)) void pagefault_handler(struct interrupt_frame *frame, __attribute__((interrupt)) void pagefault_handler(struct interrupt_frame *frame,
ulong error_code) ulong error_code)
{ {
// A page fault has occurred. // A page fault has occurred.
// The faulting address is stored in the CR2 register. // The faulting address is stored in the CR2 register.
uint32_t faulting_address; uint32_t faulting_address;
asm volatile("mov %%cr2, %0" : "=r"(faulting_address)); asm volatile("mov %%cr2, %0" : "=r"(faulting_address));
printStringDetails("PAGE FAULT", RED, BLACK, 0, VGA_HEIGHT - 1); printStringDetails("PAGE FAULT", RED, BLACK, 0, VGA_HEIGHT - 1);
printIntDetails(error_code, RED, BLACK, 11, VGA_HEIGHT - 1); printIntDetails(error_code, RED, BLACK, 11, VGA_HEIGHT - 1);
(void)faulting_address; (void)faulting_address;
(void)frame; (void)frame;
(void)error_code; (void)error_code;
} }

View File

@ -75,33 +75,32 @@ struct x86_gdt_register {
* 0..4GB addresses to be mapped to the linear 0..4GB linear * 0..4GB addresses to be mapped to the linear 0..4GB linear
* addresses. * addresses.
*/ */
#define BUILD_GDTE(descr_privilege_level, is_code) \ #define BUILD_GDTE(descr_privilege_level, is_code) \
((struct x86_segment_descriptor){ \ ((struct x86_segment_descriptor){ \
.limit_15_0 = 0xffff, \ .limit_15_0 = 0xffff, \
.base_paged_addr_15_0 = 0, \ .base_paged_addr_15_0 = 0, \
.base_paged_addr_23_16 = 0, \ .base_paged_addr_23_16 = 0, \
.segment_type = \ .segment_type = ((is_code) ? 0xb : 0x3), /* With descriptor_type (below) = 1 \
((is_code) ? 0xb : 0x3), /* With descriptor_type (below) = 1 (code/data), \ * (code/data), see Figure 3-1 of \
* see Figure 3-1 of section 3.4.3.1 in Intel \ * section 3.4.3.1 in Intel x86 vol 3: \
* x86 vol 3: \ * - Code (bit 3 = 1): \
* - Code (bit 3 = 1): \ * bit 0: 1=Accessed \
* bit 0: 1=Accessed \ * bit 1: 1=Readable \
* bit 1: 1=Readable \ * bit 2: 0=Non-Conforming \
* bit 2: 0=Non-Conforming \ * - Data (bit 3 = 0): \
* - Data (bit 3 = 0): \ * bit 0: 1=Accessed \
* bit 0: 1=Accessed \ * bit 1: 1=Writable \
* bit 1: 1=Writable \ * bit 2: 0=Expand up (stack-related) \
* bit 2: 0=Expand up (stack-related) \ * For Conforming/non conforming segments, \
* For Conforming/non conforming segments, see \ * see Intel x86 Vol 3 section 4.8.1.1 \
* Intel x86 Vol 3 section 4.8.1.1 \ */ \
*/ \ .descriptor_type = 1, /* 1=Code/Data */ \
.descriptor_type = 1, /* 1=Code/Data */ \ .dpl = ((descr_privilege_level)&0x3), \
.dpl = ((descr_privilege_level)&0x3), \ .present = 1, \
.present = 1, \ .limit_19_16 = 0xf, \
.limit_19_16 = 0xf, \ .custom = 0, \
.custom = 0, \ .op_size = 1, /* 32 bits instr/data */ \
.op_size = 1, /* 32 bits instr/data */ \ .granularity = 1 /* limit is in 4kB Pages */ \
.granularity = 1 /* limit is in 4kB Pages */ \
}) })
/** The actual GDT */ /** The actual GDT */

View File

@ -5,16 +5,16 @@
modify it under the terms of the GNU General Public License modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2 as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version. of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
USA. USA.
*/ */
#pragma once #pragma once
@ -34,4 +34,3 @@
* address space (ie "flat" virtual space). * address space (ie "flat" virtual space).
*/ */
int gdtSetup(void); int gdtSetup(void);

View File

@ -13,16 +13,16 @@
#define SEGMENT_IDX_DATA 2 #define SEGMENT_IDX_DATA 2
struct idtEntry { struct idtEntry {
uint16_t offset_low; uint16_t offset_low;
uint16_t seg_sel; uint16_t seg_sel;
uint8_t reserved : 5; uint8_t reserved : 5;
uint8_t flags : 3; uint8_t flags : 3;
uint8_t type : 3; uint8_t type : 3;
uint8_t op_size : 1; uint8_t op_size : 1;
uint8_t zero : 1; uint8_t zero : 1;
uint8_t dpl : 2; uint8_t dpl : 2;
uint8_t present : 1; uint8_t present : 1;
uint16_t offset_high; uint16_t offset_high;
} __attribute__((packed)); } __attribute__((packed));
/** /**
@ -32,14 +32,13 @@ struct idtEntry {
* @see Intel x86 doc vol 3, section 2.4, figure 2-4 * @see Intel x86 doc vol 3, section 2.4, figure 2-4
*/ */
struct idtRegister { struct idtRegister {
uint16_t limit; uint16_t limit;
uint32_t base_addr; uint32_t base_addr;
} __attribute__((packed, aligned(8))); } __attribute__((packed, aligned(8)));
/* Build segment http://wiki.osdev.org/Selector*/ /* Build segment http://wiki.osdev.org/Selector*/
#define BUILD_SEGMENT_SELECTOR(desc_privilege, in_ldt, index) \ #define BUILD_SEGMENT_SELECTOR(desc_privilege, in_ldt, index) \
((((desc_privilege)&0x3) << 0) | (((in_ldt) ? 1 : 0) << 2) | \ ((((desc_privilege)&0x3) << 0) | (((in_ldt) ? 1 : 0) << 2) | ((index) << 3))
((index) << 3))
int idtSetup(); int idtSetup();
int idt_set_handler(int index, unsigned int addr, int priviledge); int idt_set_handler(int index, unsigned int addr, int priviledge);

View File

@ -1,20 +1,19 @@
#pragma once #pragma once
#include "stdarg.h" #include "stdarg.h"
// c.f. intel software-developer-vol-1 6.4.1 // c.f. intel software-developer-vol-1 6.4.1
struct interrupt_frame { struct interrupt_frame {
uint32_t eip; uint32_t eip;
uint32_t cs; uint32_t cs;
uint32_t eflags; uint32_t eflags;
uint32_t esp; uint32_t esp;
uint32_t ss; uint32_t ss;
}; };
// Exception // Exception
// Exception // Exception
#define DECLARE_INTERRUPT(int_nb) \ #define DECLARE_INTERRUPT(int_nb) \
void print_handler_##int_nb(struct interrupt_frame *frame, ulong error_code); void print_handler_##int_nb(struct interrupt_frame *frame, ulong error_code);
#define ACCESS_INTERRUPT(int_nb) print_handler_##int_nb #define ACCESS_INTERRUPT(int_nb) print_handler_##int_nb

View File

@ -4,18 +4,17 @@
// NIH http://wiki.osdev.org/Inline_Assembly/Examples#I.2FO_access // NIH http://wiki.osdev.org/Inline_Assembly/Examples#I.2FO_access
static inline void outb(uint16_t port, uint8_t val) static inline void outb(uint16_t port, uint8_t val)
{ {
asm volatile ( "outb %0, %1" : : "a"(val), "Nd"(port) ); asm volatile("outb %0, %1" : : "a"(val), "Nd"(port));
/* There's an outb %al, $imm8 encoding, for compile-time constant port numbers that fit in 8b. (N constraint). /* There's an outb %al, $imm8 encoding, for compile-time constant port numbers that fit in
* Wider immediate constants would be truncated at assemble-time (e.g. "i" constraint). * 8b. (N constraint). Wider immediate constants would be truncated at assemble-time (e.g.
* The outb %al, %dx encoding is the only option for all other cases. * "i" constraint). The outb %al, %dx encoding is the only option for all other cases.
* %1 expands to %dx because port is a uint16_t. %w1 could be used if we had the port number a wider C type */ * %1 expands to %dx because port is a uint16_t. %w1 could be used if we had the port
* number a wider C type */
} }
static inline uint8_t inb(uint16_t port) static inline uint8_t inb(uint16_t port)
{ {
uint8_t ret; uint8_t ret;
asm volatile ( "inb %1, %0" asm volatile("inb %1, %0" : "=a"(ret) : "Nd"(port));
: "=a"(ret)
: "Nd"(port) );
return ret; return ret;
} }

View File

@ -5,11 +5,13 @@
int irqSetup() int irqSetup()
{ {
initPic(); initPic();
return 0; return 0;
} }
irq_handler irq_handler_array[IRQ_NUM] = {NULL, }; irq_handler irq_handler_array[IRQ_NUM] = {
NULL,
};
int irqSetRoutine(int irq, irq_handler handler) int irqSetRoutine(int irq, irq_handler handler)
{ {
@ -22,8 +24,8 @@ int irqSetRoutine(int irq, irq_handler handler)
irq_handler_array[irq] = handler; irq_handler_array[irq] = handler;
if (handler != NULL) { if (handler != NULL) {
int ret = int ret = idt_set_handler(IRQ_INTERRUPT_BASE_ADDRESS + irq,
idt_set_handler(IRQ_INTERRUPT_BASE_ADDRESS + irq, (unsigned int)irq_handler_array[irq], 0); (unsigned int)irq_handler_array[irq], 0);
if (!ret) if (!ret)
enableIrq(irq); enableIrq(irq);
} }

View File

@ -11,29 +11,29 @@
}) })
#define restore_IRQs(flags) restore_flags(flags) #define restore_IRQs(flags) restore_flags(flags)
#define IRQ_TIMER 0 // MASTER IRQ
#define IRQ_TIMER 0 // MASTER IRQ #define IRQ_KEYBOARD 1
#define IRQ_KEYBOARD 1 #define IRQ_SLAVE_PIC 2
#define IRQ_SLAVE_PIC 2 #define IRQ_COM2 3
#define IRQ_COM2 3 #define IRQ_COM1 4
#define IRQ_COM1 4 #define IRQ_LPT2 5
#define IRQ_LPT2 5 #define IRQ_FLOPPY 6
#define IRQ_FLOPPY 6 #define IRQ_LPT1 7
#define IRQ_LPT1 7
#define IRQ_8_NOT_DEFINED 8 // SLAVE #define IRQ_8_NOT_DEFINED 8 // SLAVE
#define IRQ_RESERVED_1 9 // SLAVE IRQ #define IRQ_RESERVED_1 9 // SLAVE IRQ
#define IRQ_RESERVED_2 10 #define IRQ_RESERVED_2 10
#define IRQ_RESERVED_3 11 #define IRQ_RESERVED_3 11
#define IRQ_RESERVED_4 12 #define IRQ_RESERVED_4 12
#define IRQ_COPROCESSOR 13 #define IRQ_COPROCESSOR 13
#define IRQ_HARDDISK 14 #define IRQ_HARDDISK 14
#define IRQ_RESERVED_5 15 #define IRQ_RESERVED_5 15
#define IRQ_INTERRUPT_BASE_ADDRESS 0x20 #define IRQ_INTERRUPT_BASE_ADDRESS 0x20
#define IRQ_NUM 16 #define IRQ_NUM 16
// An handler should finish by the iret opcode -> https://wiki.osdev.org/Interrupt_Service_Routines // An handler should finish by the iret opcode ->
// That's why we use wrapper around them or the gcc interrupt attribut // https://wiki.osdev.org/Interrupt_Service_Routines That's why we use wrapper around them or
// the gcc interrupt attribut
// __attribute__((interrupt)) void (*irq_handler)(int irq); // __attribute__((interrupt)) void (*irq_handler)(int irq);
typedef void (*irq_handler)(struct interrupt_frame *frame); typedef void (*irq_handler)(struct interrupt_frame *frame);
int irqSetup(); int irqSetup();

View File

@ -9,21 +9,21 @@
// Need GCC > 6 // Need GCC > 6
__attribute__((interrupt)) void keyboard_handler(struct interrupt_frame *frame) __attribute__((interrupt)) void keyboard_handler(struct interrupt_frame *frame)
{ {
EOIIrq(IRQ_KEYBOARD); EOIIrq(IRQ_KEYBOARD);
keyboard_do_irq(); keyboard_do_irq();
(void)frame; (void)frame;
} }
__attribute__((interrupt)) void timer_handler(struct interrupt_frame *frame) __attribute__((interrupt)) void timer_handler(struct interrupt_frame *frame)
{ {
static int timeCnt = 0; static int timeCnt = 0;
EOIIrq(IRQ_TIMER); EOIIrq(IRQ_TIMER);
printIntDetails(timeCnt++, RED, BLACK, 20, VGA_HEIGHT - 1); printIntDetails(timeCnt++, RED, BLACK, 20, VGA_HEIGHT - 1);
(void)frame; (void)frame;
} }
__attribute__((interrupt)) void serial_handler(struct interrupt_frame *frame) __attribute__((interrupt)) void serial_handler(struct interrupt_frame *frame)
{ {
EOIIrq(IRQ_COM1); EOIIrq(IRQ_COM1);
serialDoIrq(frame); serialDoIrq(frame);
} }

View File

@ -1,13 +1,13 @@
#pragma once #pragma once
#include "stdarg.h" #include "stdarg.h"
#define islower(c) (('a' <= (c)) && ((c) <= 'z')) #define islower(c) (('a' <= (c)) && ((c) <= 'z'))
#define isupper(c) (('A' <= (c)) && ((c) <= 'Z')) #define isupper(c) (('A' <= (c)) && ((c) <= 'Z'))
#define isdigit(c) (('0' <= (c)) && ((c) <= '9')) #define isdigit(c) (('0' <= (c)) && ((c) <= '9'))
#define isspace(c) (((c) == ' ') || ((c) == '\t') || \ #define isspace(c) \
((c) == '\f') || ((c) == '\n') || \ (((c) == ' ') || ((c) == '\t') || ((c) == '\f') || ((c) == '\n') || ((c) == '\r') || \
((c) == '\r') || ((c) == '\v')) ((c) == '\v'))
#define isprint(c) ((' ' <= (c)) && ((c) <= '~')) #define isprint(c) ((' ' <= (c)) && ((c) <= '~'))
int memcmp(const void *s1, const void *s2, size_t n); int memcmp(const void *s1, const void *s2, size_t n);
void *memcpy(void *dest, const void *src, size_t n); void *memcpy(void *dest, const void *src, size_t n);
@ -15,7 +15,7 @@ void *memset(void *s, int c, size_t n);
char *itoa(int value, char *str, int base); char *itoa(int value, char *str, int base);
void reverse(char s[]); void reverse(char s[]);
int strlen(const char s[]); int strlen(const char s[]);
unsigned int strnlen(const char * s, size_t count); unsigned int strnlen(const char *s, size_t count);
int strcmp(const char s1[], const char s2[]); int strcmp(const char s1[], const char s2[]);
char *strzcpy(char *dst, const char *src, int len); char *strzcpy(char *dst, const char *src, int len);
void puts(const char *str); void puts(const char *str);
@ -28,20 +28,17 @@ void printf(const char *format, ...);
* Dummy printk for disabled debugging statements to use whilst maintaining * Dummy printk for disabled debugging statements to use whilst maintaining
* gcc's format checking. * gcc's format checking.
*/ */
#define no_printf(fmt, ...) \ #define no_printf(fmt, ...) \
({ \ ({ \
if (0) \ if (0) \
printf(fmt, ##__VA_ARGS__); \ printf(fmt, ##__VA_ARGS__); \
0; \ 0; \
}) })
#ifdef DEBUG #ifdef DEBUG
#define pr_devel(fmt, ...) \ #define pr_devel(fmt, ...) printf(pr_fmt(fmt), ##__VA_ARGS__)
printf(pr_fmt(fmt), ##__VA_ARGS__)
#else #else
#define pr_devel(fmt, ...) \ #define pr_devel(fmt, ...) no_printf(pr_fmt(fmt), ##__VA_ARGS__)
no_printf(pr_fmt(fmt), ##__VA_ARGS__)
#endif #endif
#define pr_info(fmt, ...) \ #define pr_info(fmt, ...) printf(pr_fmt(fmt), ##__VA_ARGS__)
printf(pr_fmt(fmt), ##__VA_ARGS__)

View File

@ -10,96 +10,96 @@ static struct kthread *currentThread;
void kthreadExit() void kthreadExit()
{ {
uint32_t flags; uint32_t flags;
disable_IRQs(flags); disable_IRQs(flags);
struct kthread *current = currentThread; struct kthread *current = currentThread;
struct kthread *next = kthreadSelectNext(); struct kthread *next = kthreadSelectNext();
if (next == current) if (next == current)
assert("cannot exit thread"); assert("cannot exit thread");
currentThread = next; currentThread = next;
cpu_context_exit_to(next->cpuState, (cpu_kstate_function_arg1_t *)kthreadDelete, cpu_context_exit_to(next->cpuState, (cpu_kstate_function_arg1_t *)kthreadDelete,
(uint32_t)current); (uint32_t)current);
restore_IRQs(flags); restore_IRQs(flags);
return; return;
} }
int kthreadSetup(vaddr_t mainStack, size_t mainStackSize) int kthreadSetup(vaddr_t mainStack, size_t mainStackSize)
{ {
struct kthread *current = (struct kthread *)malloc(sizeof(struct kthread)); struct kthread *current = (struct kthread *)malloc(sizeof(struct kthread));
strzcpy(current->name, "[KINIT]", KTHREAD_NAME_MAX_LENGTH); strzcpy(current->name, "[KINIT]", KTHREAD_NAME_MAX_LENGTH);
current->stackAddr = mainStack; current->stackAddr = mainStack;
current->stackSize = mainStackSize; current->stackSize = mainStackSize;
list_singleton(currentThread, current); list_singleton(currentThread, current);
return 0; return 0;
} }
struct kthread *kthreadCreate(const char *name, cpu_kstate_function_arg1_t func, void *args) struct kthread *kthreadCreate(const char *name, cpu_kstate_function_arg1_t func, void *args)
{ {
struct kthread *thread = (struct kthread *)malloc(sizeof(struct kthread)); struct kthread *thread = (struct kthread *)malloc(sizeof(struct kthread));
if (!thread) if (!thread)
return NULL;
thread->stackAddr = (vaddr_t)malloc(KTHREAD_DEFAULT_STACK_SIZE);
printf("Alloc stask at 0x%x strcut at 0x%x\n", thread->stackAddr, thread);
thread->stackSize = KTHREAD_DEFAULT_STACK_SIZE;
if (!thread->stackAddr)
goto free_mem;
if (name)
strzcpy(thread->name, name, KTHREAD_NAME_MAX_LENGTH);
else
strzcpy(thread->name, "[UNKNOW]", KTHREAD_NAME_MAX_LENGTH);
if (cpu_kstate_init(&thread->cpuState, (cpu_kstate_function_arg1_t *)func,
(vaddr_t)args, thread->stackAddr, thread->stackSize,
(cpu_kstate_function_arg1_t *)kthreadExit, 0))
goto free_mem;
list_add_tail(currentThread, thread);
return thread;
free_mem:
free((void *)thread->stackAddr);
free((void *)thread);
return NULL; return NULL;
thread->stackAddr = (vaddr_t)malloc(KTHREAD_DEFAULT_STACK_SIZE);
printf("Alloc stask at 0x%x strcut at 0x%x\n", thread->stackAddr, thread);
thread->stackSize = KTHREAD_DEFAULT_STACK_SIZE;
if (!thread->stackAddr)
goto free_mem;
if (name)
strzcpy(thread->name, name, KTHREAD_NAME_MAX_LENGTH);
else
strzcpy(thread->name, "[UNKNOW]", KTHREAD_NAME_MAX_LENGTH);
if (cpu_kstate_init(&thread->cpuState, (cpu_kstate_function_arg1_t *)func, (vaddr_t)args,
thread->stackAddr, thread->stackSize,
(cpu_kstate_function_arg1_t *)kthreadExit, 0))
goto free_mem;
list_add_tail(currentThread, thread);
return thread;
free_mem:
free((void *)thread->stackAddr);
free((void *)thread);
return NULL;
} }
void kthreadDelete(struct kthread *thread) void kthreadDelete(struct kthread *thread)
{ {
list_delete(currentThread, thread); list_delete(currentThread, thread);
free((void *)thread->stackAddr); free((void *)thread->stackAddr);
free((void *)thread); free((void *)thread);
} }
struct kthread *kthreadSelectNext() struct kthread *kthreadSelectNext()
{ {
struct kthread *nextThread = currentThread->next; struct kthread *nextThread = currentThread->next;
return nextThread; return nextThread;
} }
struct cpu_state *switchKthread(struct cpu_state *prevCpu) struct cpu_state *switchKthread(struct cpu_state *prevCpu)
{ {
uint32_t flags; uint32_t flags;
disable_IRQs(flags); disable_IRQs(flags);
currentThread->cpuState = prevCpu; currentThread->cpuState = prevCpu;
struct kthread *nextThread = kthreadSelectNext(); struct kthread *nextThread = kthreadSelectNext();
printStringDetails(nextThread->name, RED, BLACK, 40, VGA_HEIGHT - 1); printStringDetails(nextThread->name, RED, BLACK, 40, VGA_HEIGHT - 1);
currentThread = nextThread; currentThread = nextThread;
restore_IRQs(flags); restore_IRQs(flags);
return nextThread->cpuState; return nextThread->cpuState;
} }
int kthreadYield() int kthreadYield()
{ {
uint32_t flags; uint32_t flags;
disable_IRQs(flags); disable_IRQs(flags);
struct kthread *next = kthreadSelectNext(); struct kthread *next = kthreadSelectNext();
struct kthread *current = currentThread; struct kthread *current = currentThread;
currentThread = next; currentThread = next;
cpu_context_switch(&current->cpuState, next->cpuState); cpu_context_switch(&current->cpuState, next->cpuState);
restore_IRQs(flags); restore_IRQs(flags);
return 0; return 0;
} }

View File

@ -7,12 +7,12 @@
#define KTHREAD_DEFAULT_STACK_SIZE PAGE_SIZE #define KTHREAD_DEFAULT_STACK_SIZE PAGE_SIZE
struct kthread { struct kthread {
char name[KTHREAD_NAME_MAX_LENGTH]; char name[KTHREAD_NAME_MAX_LENGTH];
struct cpu_state *cpuState; struct cpu_state *cpuState;
vaddr_t stackAddr; vaddr_t stackAddr;
size_t stackSize; size_t stackSize;
struct kthread *next; struct kthread *next;
struct kthread *prev; struct kthread *prev;
}; };
int kthreadSetup(vaddr_t mainStack, size_t mainStackSize); int kthreadSetup(vaddr_t mainStack, size_t mainStackSize);

View File

@ -1,15 +1,15 @@
/* Copyright (C) 2001 David Decotigny /* Copyright (C) 2001 David Decotigny
This program is free software; you can redistribute it and/or This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2 as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version. of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
@ -25,170 +25,165 @@
* macros * macros
*/ */
/* *_named are used when next and prev links are not exactly next /* *_named are used when next and prev links are not exactly next
and prev. For instance when we have next_in_team, prev_in_team, and prev. For instance when we have next_in_team, prev_in_team,
prev_global and next_global */ prev_global and next_global */
#define list_init_named(list,prev,next) \ #define list_init_named(list, prev, next) ((list) = NULL)
((list) = NULL)
#define list_singleton_named(list,item,prev,next) ({ \ #define list_singleton_named(list, item, prev, next) \
(item)->next = (item)->prev = (item); \ ({ \
(list) = (item); \ (item)->next = (item)->prev = (item); \
}) (list) = (item); \
})
#define list_is_empty_named(list,prev,next) \ #define list_is_empty_named(list, prev, next) ((list) == NULL)
((list) == NULL)
#define list_is_singleton_named(list,prev,next) \ #define list_is_singleton_named(list, prev, next) \
( ((list) != NULL) && ((list)->prev == (list)->next) && ((list) == (list)->next) ) (((list) != NULL) && ((list)->prev == (list)->next) && ((list) == (list)->next))
#define list_get_head_named(list,prev,next) \ #define list_get_head_named(list, prev, next) (list)
(list)
#define list_get_tail_named(list,prev,next) \ #define list_get_tail_named(list, prev, next) ((list) ? ((list)->prev) : NULL)
((list)?((list)->prev):NULL)
/* Internal macro : insert before the head == insert at tail */ /* Internal macro : insert before the head == insert at tail */
#define __list_insert_atleft_named(before_this,item,prev,next) ({ \ #define __list_insert_atleft_named(before_this, item, prev, next) \
(before_this)->prev->next = (item); \ ({ \
(item)->prev = (before_this)->prev; \ (before_this)->prev->next = (item); \
(before_this)->prev = (item); \ (item)->prev = (before_this)->prev; \
(item)->next = (before_this); \ (before_this)->prev = (item); \
}) (item)->next = (before_this); \
})
/* @note Before_this and item are expected to be valid ! */ /* @note Before_this and item are expected to be valid ! */
#define list_insert_before_named(list,before_this,item,prev,next) ({ \ #define list_insert_before_named(list, before_this, item, prev, next) \
__list_insert_atleft_named(before_this,item,prev,next); \ ({ \
if ((list) == (before_this)) (list) = (item); \ __list_insert_atleft_named(before_this, item, prev, next); \
}) if ((list) == (before_this)) \
(list) = (item); \
})
/** @note After_this and item are expected to be valid ! */ /** @note After_this and item are expected to be valid ! */
#define list_insert_after_named(list,after_this,item,prev,next) ({ \ #define list_insert_after_named(list, after_this, item, prev, next) \
(after_this)->next->prev = (item); \ ({ \
(item)->next = (after_this)->next; \ (after_this)->next->prev = (item); \
(after_this)->next = (item); \ (item)->next = (after_this)->next; \
(item)->prev = (after_this); \ (after_this)->next = (item); \
}) (item)->prev = (after_this); \
})
#define list_add_head_named(list,item,prev,next) ({ \ #define list_add_head_named(list, item, prev, next) \
if (list) \ ({ \
list_insert_before_named(list,list,item,prev,next); \ if (list) \
else \ list_insert_before_named(list, list, item, prev, next); \
list_singleton_named(list,item,prev,next); \ else \
(list) = (item); \ list_singleton_named(list, item, prev, next); \
}) (list) = (item); \
})
#define list_add_tail_named(list,item,prev,next) ({ \ #define list_add_tail_named(list, item, prev, next) \
if (list) \ ({ \
__list_insert_atleft_named(list,item,prev,next); \ if (list) \
else \ __list_insert_atleft_named(list, item, prev, next); \
list_singleton_named(list,item,prev,next); \ else \
}) list_singleton_named(list, item, prev, next); \
})
/** @note NO check whether item really is in list ! */ /** @note NO check whether item really is in list ! */
#define list_delete_named(list,item,prev,next) ({ \ #define list_delete_named(list, item, prev, next) \
if ( ((item)->next == (item)) && ((item)->prev == (item)) ) \ ({ \
(item)->next = (item)->prev = (list) = NULL; \ if (((item)->next == (item)) && ((item)->prev == (item))) \
else { \ (item)->next = (item)->prev = (list) = NULL; \
(item)->prev->next = (item)->next; \ else { \
(item)->next->prev = (item)->prev; \ (item)->prev->next = (item)->next; \
if ((item) == (list)) (list) = (item)->next; \ (item)->next->prev = (item)->prev; \
(item)->prev = (item)->next = NULL; \ if ((item) == (list)) \
} \ (list) = (item)->next; \
}) (item)->prev = (item)->next = NULL; \
} \
})
#define list_pop_head_named(list,prev,next) ({ \ #define list_pop_head_named(list, prev, next) \
typeof(list) __ret_elt = (list); \ ({ \
list_delete_named(list,__ret_elt,prev,next); \ typeof(list) __ret_elt = (list); \
__ret_elt; }) list_delete_named(list, __ret_elt, prev, next); \
__ret_elt; \
})
/** Loop statement that iterates through all of its elements, from /** Loop statement that iterates through all of its elements, from
head to tail */ head to tail */
#define list_foreach_forward_named(list,iterator,nb_elements,prev,next) \ #define list_foreach_forward_named(list, iterator, nb_elements, prev, next) \
for (nb_elements=0, (iterator) = (list) ; \ for (nb_elements = 0, (iterator) = (list); \
(iterator) && (!nb_elements || ((iterator) != (list))) ; \ (iterator) && (!nb_elements || ((iterator) != (list))); \
nb_elements++, (iterator) = (iterator)->next ) nb_elements++, (iterator) = (iterator)->next)
/** Loop statement that iterates through all of its elements, from /** Loop statement that iterates through all of its elements, from
tail back to head */ tail back to head */
#define list_foreach_backward_named(list,iterator,nb_elements,prev,next) \ #define list_foreach_backward_named(list, iterator, nb_elements, prev, next) \
for (nb_elements=0, (iterator) = list_get_tail_named(list,prev,next) ; \ for (nb_elements = 0, (iterator) = list_get_tail_named(list, prev, next); \
(iterator) && (!nb_elements || \ (iterator) && \
((iterator) != list_get_tail_named(list,prev,next))) ; \ (!nb_elements || ((iterator) != list_get_tail_named(list, prev, next))); \
nb_elements++, (iterator) = (iterator)->prev ) nb_elements++, (iterator) = (iterator)->prev)
#define list_foreach_named list_foreach_forward_named #define list_foreach_named list_foreach_forward_named
/** True when we exitted early from the foreach loop (ie break) */ /** True when we exitted early from the foreach loop (ie break) */
#define list_foreach_early_break(list,iterator,nb_elements) \ #define list_foreach_early_break(list, iterator, nb_elements) \
((list) && ( \ ((list) && (((list) != (iterator)) || (((list) == (iterator)) && (nb_elements == 0))))
((list) != (iterator)) || \
( ((list) == (iterator)) && (nb_elements == 0)) ))
/** Loop statement that also removes the item at each iteration. The /** Loop statement that also removes the item at each iteration. The
body of the loop is allowed to delete the iterator element from body of the loop is allowed to delete the iterator element from
memory. */ memory. */
#define list_collapse_named(list,iterator,prev,next) \ #define list_collapse_named(list, iterator, prev, next) \
for ( ; ({ ((iterator) = (list)) ; \ for (; ({ \
if (list) list_delete_named(list,iterator,prev,next) ; \ ((iterator) = (list)); \
(iterator); }) ; ) if (list) \
list_delete_named(list, iterator, prev, next); \
(iterator); \
});)
/* /*
* the same macros : assume that the prev and next fields are really * the same macros : assume that the prev and next fields are really
* named "prev" and "next" * named "prev" and "next"
*/ */
#define list_init(list) \ #define list_init(list) list_init_named(list, prev, next)
list_init_named(list,prev,next)
#define list_singleton(list,item) \ #define list_singleton(list, item) list_singleton_named(list, item, prev, next)
list_singleton_named(list,item,prev,next)
#define list_is_empty(list) \ #define list_is_empty(list) list_is_empty_named(list, prev, next)
list_is_empty_named(list,prev,next)
#define list_is_singleton(list) \ #define list_is_singleton(list) list_is_singleton_named(list, prev, next)
list_is_singleton_named(list,prev,next)
#define list_get_head(list) \ #define list_get_head(list) list_get_head_named(list, prev, next)
list_get_head_named(list,prev,next) \
#define list_get_tail(list) \ #define list_get_tail(list) list_get_tail_named(list, prev, next)
list_get_tail_named(list,prev,next) \
/* @note Before_this and item are expected to be valid ! */ /* @note Before_this and item are expected to be valid ! */
#define list_insert_after(list,after_this,item) \ #define list_insert_after(list, after_this, item) \
list_insert_after_named(list,after_this,item,prev,next) list_insert_after_named(list, after_this, item, prev, next)
/* @note After_this and item are expected to be valid ! */ /* @note After_this and item are expected to be valid ! */
#define list_insert_before(list,before_this,item) \ #define list_insert_before(list, before_this, item) \
list_insert_before_named(list,before_this,item,prev,next) list_insert_before_named(list, before_this, item, prev, next)
#define list_add_head(list,item) \ #define list_add_head(list, item) list_add_head_named(list, item, prev, next)
list_add_head_named(list,item,prev,next)
#define list_add_tail(list,item) \ #define list_add_tail(list, item) list_add_tail_named(list, item, prev, next)
list_add_tail_named(list,item,prev,next)
/* @note NO check whether item really is in list ! */ /* @note NO check whether item really is in list ! */
#define list_delete(list,item) \ #define list_delete(list, item) list_delete_named(list, item, prev, next)
list_delete_named(list,item,prev,next)
#define list_pop_head(list) \ #define list_pop_head(list) list_pop_head_named(list, prev, next)
list_pop_head_named(list,prev,next)
#define list_foreach_forward(list,iterator,nb_elements) \ #define list_foreach_forward(list, iterator, nb_elements) \
list_foreach_forward_named(list,iterator,nb_elements,prev,next) list_foreach_forward_named(list, iterator, nb_elements, prev, next)
#define list_foreach_backward(list,iterator,nb_elements) \ #define list_foreach_backward(list, iterator, nb_elements) \
list_foreach_backward_named(list,iterator,nb_elements,prev,next) list_foreach_backward_named(list, iterator, nb_elements, prev, next)
#define list_foreach list_foreach_forward #define list_foreach list_foreach_forward
#define list_collapse(list,iterator) \ #define list_collapse(list, iterator) list_collapse_named(list, iterator, prev, next)
list_collapse_named(list,iterator,prev,next)
#endif /* _SOS_LIST_H_ */ #endif /* _SOS_LIST_H_ */

View File

@ -26,14 +26,14 @@ void cpuid(int code, uint32_t *a, uint32_t *d)
asm volatile("cpuid" : "=a"(*a), "=d"(*d) : "0"(code) : "ebx", "ecx"); asm volatile("cpuid" : "=a"(*a), "=d"(*d) : "0"(code) : "ebx", "ecx");
} }
void idleThread(void *arg){ void idleThread(void *arg)
{
(void)arg; (void)arg;
int count = 0; int count = 0;
while(1) while (1)
printIntDetails(count++, GREEN, BLACK, 0, VGA_HEIGHT - 1); printIntDetails(count++, GREEN, BLACK, 0, VGA_HEIGHT - 1);
} }
// Multiboot information available here : // Multiboot information available here :
// https://www.gnu.org/software/grub/manual/multiboot/multiboot.html#kernel_002ec // https://www.gnu.org/software/grub/manual/multiboot/multiboot.html#kernel_002ec
// https://www.gnu.org/software/grub/manual/multiboot/html_node/Boot-information-format.html#Boot%20information%20format // https://www.gnu.org/software/grub/manual/multiboot/html_node/Boot-information-format.html#Boot%20information%20format
@ -83,7 +83,7 @@ void kmain(unsigned long magic, unsigned long addr)
struct multiboot_mmap_entry *mmap = (struct multiboot_mmap_entry *)mbi->mmap_addr; struct multiboot_mmap_entry *mmap = (struct multiboot_mmap_entry *)mbi->mmap_addr;
uint size = mbi->mmap_length / sizeof(struct multiboot_mmap_entry); uint size = mbi->mmap_length / sizeof(struct multiboot_mmap_entry);
pr_devel("mmap buffer at %d size %d %d\n", mbi->mmap_addr, mbi->mmap_length, pr_devel("mmap buffer at %d size %d %d\n", mbi->mmap_addr, mbi->mmap_length,
sizeof(multiboot_memory_map_t)); sizeof(multiboot_memory_map_t));
for (uint i = 0; i < size; i++) { for (uint i = 0; i < size; i++) {
printf("base_addr 0x%x 0x%x, length = 0x%x 0x%x, type = 0x%x\n", printf("base_addr 0x%x 0x%x, length = 0x%x 0x%x, type = 0x%x\n",
(unsigned)(mmap[i].addr >> 32), (unsigned)(mmap[i].addr & 0xffffffff), (unsigned)(mmap[i].addr >> 32), (unsigned)(mmap[i].addr & 0xffffffff),
@ -112,8 +112,8 @@ void kmain(unsigned long magic, unsigned long addr)
printf("Enabling HW interrupts\n"); printf("Enabling HW interrupts\n");
exceptionSetRoutine(EXCEPTION_DOUBLE_FAULT, ACCESS_INTERRUPT(EXCEPTION_DOUBLE_FAULT)); exceptionSetRoutine(EXCEPTION_DOUBLE_FAULT, ACCESS_INTERRUPT(EXCEPTION_DOUBLE_FAULT));
exceptionSetRoutine(EXCEPTION_DIVIDE_ZERO, ACCESS_INTERRUPT(EXCEPTION_DIVIDE_ZERO)); exceptionSetRoutine(EXCEPTION_DIVIDE_ZERO, ACCESS_INTERRUPT(EXCEPTION_DIVIDE_ZERO));
//Used by the DBG // Used by the DBG
//exceptionSetRoutine(EXCEPTION_DEBUG, ACCESS_INTERRUPT(EXCEPTION_DEBUG)); // exceptionSetRoutine(EXCEPTION_DEBUG, ACCESS_INTERRUPT(EXCEPTION_DEBUG));
exceptionSetRoutine(EXCEPTION_NMI, ACCESS_INTERRUPT(EXCEPTION_NMI)); exceptionSetRoutine(EXCEPTION_NMI, ACCESS_INTERRUPT(EXCEPTION_NMI));
exceptionSetRoutine(EXCEPTION_BREAKPOINT, ACCESS_INTERRUPT(EXCEPTION_BREAKPOINT)); exceptionSetRoutine(EXCEPTION_BREAKPOINT, ACCESS_INTERRUPT(EXCEPTION_BREAKPOINT));
exceptionSetRoutine(EXCEPTION_OVERFLOW, ACCESS_INTERRUPT(EXCEPTION_OVERFLOW)); exceptionSetRoutine(EXCEPTION_OVERFLOW, ACCESS_INTERRUPT(EXCEPTION_OVERFLOW));

View File

@ -1,11 +1,9 @@
#include "math.h" #include "math.h"
inline uint32_t log2(const uint32_t x) { inline uint32_t log2(const uint32_t x)
uint32_t y; {
// Get the highest set bit uint32_t y;
asm ( "\tbsr %1, %0\n" // Get the highest set bit
: "=r"(y) asm("\tbsr %1, %0\n" : "=r"(y) : "r"(x));
: "r" (x) return y;
);
return y;
} }

View File

@ -1,7 +1,7 @@
#include "mem.h" #include "mem.h"
#include "klibc.h"
#include "list.h" #include "list.h"
#include "types.h" #include "types.h"
#include "klibc.h"
static struct mem_desc *page_desc = (struct mem_desc *)&__ld_kernel_end; static struct mem_desc *page_desc = (struct mem_desc *)&__ld_kernel_end;
static struct mem_desc *free_page; static struct mem_desc *free_page;
@ -13,89 +13,88 @@ static unsigned long allocatedPage = 0;
int memSetup(paddr_t upperMem, paddr_t *lastUsedOut) int memSetup(paddr_t upperMem, paddr_t *lastUsedOut)
{ {
// Align upper mem (in kB) on page size even if it does loose a page // Align upper mem (in kB) on page size even if it does loose a page
upperMem = ALIGN_DOWN(upperMem, PAGE_SIZE / 1024); upperMem = ALIGN_DOWN(upperMem, PAGE_SIZE / 1024);
printf("Available Mem from 0x%x to 0x%x: %dMB \n", &__ld_kernel_end, upperMem * 1024, printf("Available Mem from 0x%x to 0x%x: %dMB \n", &__ld_kernel_end, upperMem * 1024,
(upperMem * 1024 - (uint32_t)&__ld_kernel_end) / (1024*1024)); (upperMem * 1024 - (uint32_t)&__ld_kernel_end) / (1024 * 1024));
// Memory description is stored after the kernel. We need some place to store it // Memory description is stored after the kernel. We need some place to store it
unsigned long memdesc_end = unsigned long memdesc_end =
(unsigned long)page_desc + (unsigned long)page_desc + ((upperMem) / (PAGE_SIZE / 1024)) * sizeof(struct mem_desc);
((upperMem) / (PAGE_SIZE / 1024)) * sizeof(struct mem_desc); uint lastUsed = (memdesc_end >> PAGE_SHIFT) + 1;
uint lastUsed = (memdesc_end >> PAGE_SHIFT) + 1; list_init(free_page);
list_init(free_page); list_init(used_page);
list_init(used_page); bottom_mem = lastUsed;
bottom_mem = lastUsed; *lastUsedOut = memdesc_end;
*lastUsedOut = memdesc_end; top_mem = upperMem * 1024;
top_mem = upperMem * 1024; for (uint i = 0; i < (upperMem / (PAGE_SIZE / 1024)); i++) {
for (uint i = 0; i < (upperMem / (PAGE_SIZE / 1024)); i++) { struct mem_desc *mem = &page_desc[i];
struct mem_desc *mem = &page_desc[i]; if (i < lastUsed) {
if (i < lastUsed) { mem->ref = 1;
mem->ref = 1; list_add_tail(used_page, mem);
list_add_tail(used_page, mem); } else {
} else { mem->ref = 0;
mem->ref = 0; list_add_tail(free_page, mem);
list_add_tail(free_page, mem); }
} mem->phy_addr = i * PAGE_SIZE;
mem->phy_addr = i * PAGE_SIZE; }
} return 0;
return 0;
} }
struct mem_desc *addr2memDesc(paddr_t addr) struct mem_desc *addr2memDesc(paddr_t addr)
{ {
if (addr > top_mem || addr < bottom_mem) if (addr > top_mem || addr < bottom_mem)
return NULL; return NULL;
int idx = addr >> PAGE_SHIFT; int idx = addr >> PAGE_SHIFT;
return page_desc + idx; return page_desc + idx;
} }
paddr_t allocPhyPage(void) paddr_t allocPhyPage(void)
{ {
if (list_is_empty(free_page)) { if (list_is_empty(free_page)) {
return (unsigned long)NULL; return (unsigned long)NULL;
} }
struct mem_desc *mem = list_pop_head(free_page); struct mem_desc *mem = list_pop_head(free_page);
mem->ref = 1; mem->ref = 1;
list_add_tail(used_page, mem); list_add_tail(used_page, mem);
allocatedPage++; allocatedPage++;
return mem->phy_addr; return mem->phy_addr;
} }
int unrefPhyPage(paddr_t addr) int unrefPhyPage(paddr_t addr)
{ {
struct mem_desc *mem = addr2memDesc(addr); struct mem_desc *mem = addr2memDesc(addr);
if (!mem) { if (!mem) {
return -1; return -1;
} }
mem->ref--; mem->ref--;
if (mem->ref == 0) { if (mem->ref == 0) {
allocatedPage--; allocatedPage--;
list_delete(used_page, mem); list_delete(used_page, mem);
list_add_tail(free_page, mem); list_add_tail(free_page, mem);
} }
return mem->ref; return mem->ref;
} }
int refPhyPage(paddr_t addr) int refPhyPage(paddr_t addr)
{ {
struct mem_desc *mem = addr2memDesc(addr); struct mem_desc *mem = addr2memDesc(addr);
if (!mem) { if (!mem) {
return -1; return -1;
} }
mem->ref++; mem->ref++;
if (mem->ref == 1) { if (mem->ref == 1) {
allocatedPage++; allocatedPage++;
list_add_tail(used_page, mem); list_add_tail(used_page, mem);
list_delete(free_page, mem); list_delete(free_page, mem);
} }
return 0; return 0;
} }
unsigned long getNbAllocatedPage(void) unsigned long getNbAllocatedPage(void)
{ {
return allocatedPage; return allocatedPage;
} }

View File

@ -1,7 +1,6 @@
#pragma once #pragma once
#include "types.h"
#include "stdarg.h" #include "stdarg.h"
#include "types.h"
#define PAGE_SHIFT 12U #define PAGE_SHIFT 12U
#define PAGE_SIZE (1U << PAGE_SHIFT) #define PAGE_SIZE (1U << PAGE_SHIFT)
@ -10,13 +9,12 @@
extern uint32_t __ld_kernel_begin; extern uint32_t __ld_kernel_begin;
extern uint32_t __ld_kernel_end; extern uint32_t __ld_kernel_end;
struct mem_desc{ struct mem_desc {
paddr_t phy_addr; paddr_t phy_addr;
long ref; long ref;
struct mem_desc *next, *prev; struct mem_desc *next, *prev;
}; };
int memSetup(paddr_t upperMem, paddr_t *lastUsed); int memSetup(paddr_t upperMem, paddr_t *lastUsed);
paddr_t allocPhyPage(void); paddr_t allocPhyPage(void);
int unrefPhyPage(paddr_t addr); int unrefPhyPage(paddr_t addr);

View File

@ -98,164 +98,164 @@ typedef unsigned int multiboot_uint32_t;
typedef unsigned long long multiboot_uint64_t; typedef unsigned long long multiboot_uint64_t;
struct multiboot_header { struct multiboot_header {
/* Must be MULTIBOOT_MAGIC - see above. */ /* Must be MULTIBOOT_MAGIC - see above. */
multiboot_uint32_t magic; multiboot_uint32_t magic;
/* Feature flags. */ /* Feature flags. */
multiboot_uint32_t flags; multiboot_uint32_t flags;
/* The above fields plus this one must equal 0 mod 2^32. */ /* The above fields plus this one must equal 0 mod 2^32. */
multiboot_uint32_t checksum; multiboot_uint32_t checksum;
/* These are only valid if MULTIBOOT_AOUT_KLUDGE is set. */ /* These are only valid if MULTIBOOT_AOUT_KLUDGE is set. */
multiboot_uint32_t header_addr; multiboot_uint32_t header_addr;
multiboot_uint32_t load_addr; multiboot_uint32_t load_addr;
multiboot_uint32_t load_end_addr; multiboot_uint32_t load_end_addr;
multiboot_uint32_t bss_end_addr; multiboot_uint32_t bss_end_addr;
multiboot_uint32_t entry_addr; multiboot_uint32_t entry_addr;
/* These are only valid if MULTIBOOT_VIDEO_MODE is set. */ /* These are only valid if MULTIBOOT_VIDEO_MODE is set. */
multiboot_uint32_t mode_type; multiboot_uint32_t mode_type;
multiboot_uint32_t width; multiboot_uint32_t width;
multiboot_uint32_t height; multiboot_uint32_t height;
multiboot_uint32_t depth; multiboot_uint32_t depth;
}; };
/* The symbol table for a.out. */ /* The symbol table for a.out. */
struct multiboot_aout_symbol_table { struct multiboot_aout_symbol_table {
multiboot_uint32_t tabsize; multiboot_uint32_t tabsize;
multiboot_uint32_t strsize; multiboot_uint32_t strsize;
multiboot_uint32_t addr; multiboot_uint32_t addr;
multiboot_uint32_t reserved; multiboot_uint32_t reserved;
}; };
typedef struct multiboot_aout_symbol_table multiboot_aout_symbol_table_t; typedef struct multiboot_aout_symbol_table multiboot_aout_symbol_table_t;
/* The section header table for ELF. */ /* The section header table for ELF. */
struct multiboot_elf_section_header_table { struct multiboot_elf_section_header_table {
multiboot_uint32_t num; multiboot_uint32_t num;
multiboot_uint32_t size; multiboot_uint32_t size;
multiboot_uint32_t addr; multiboot_uint32_t addr;
multiboot_uint32_t shndx; multiboot_uint32_t shndx;
}; };
typedef struct multiboot_elf_section_header_table multiboot_elf_section_header_table_t; typedef struct multiboot_elf_section_header_table multiboot_elf_section_header_table_t;
struct multiboot_info { struct multiboot_info {
/* Multiboot info version number */ /* Multiboot info version number */
multiboot_uint32_t flags; multiboot_uint32_t flags;
/* Available memory from BIOS */ /* Available memory from BIOS */
multiboot_uint32_t mem_lower; multiboot_uint32_t mem_lower;
multiboot_uint32_t mem_upper; multiboot_uint32_t mem_upper;
/* "root" partition */ /* "root" partition */
multiboot_uint32_t boot_device; multiboot_uint32_t boot_device;
/* Kernel command line */ /* Kernel command line */
multiboot_uint32_t cmdline; multiboot_uint32_t cmdline;
/* Boot-Module list */ /* Boot-Module list */
multiboot_uint32_t mods_count; multiboot_uint32_t mods_count;
multiboot_uint32_t mods_addr; multiboot_uint32_t mods_addr;
union { union {
multiboot_aout_symbol_table_t aout_sym; multiboot_aout_symbol_table_t aout_sym;
multiboot_elf_section_header_table_t elf_sec; multiboot_elf_section_header_table_t elf_sec;
} u; } u;
/* Memory Mapping buffer */ /* Memory Mapping buffer */
multiboot_uint32_t mmap_length; multiboot_uint32_t mmap_length;
multiboot_uint32_t mmap_addr; multiboot_uint32_t mmap_addr;
/* Drive Info buffer */ /* Drive Info buffer */
multiboot_uint32_t drives_length; multiboot_uint32_t drives_length;
multiboot_uint32_t drives_addr; multiboot_uint32_t drives_addr;
/* ROM configuration table */ /* ROM configuration table */
multiboot_uint32_t config_table; multiboot_uint32_t config_table;
/* Boot Loader Name */ /* Boot Loader Name */
multiboot_uint32_t boot_loader_name; multiboot_uint32_t boot_loader_name;
/* APM table */ /* APM table */
multiboot_uint32_t apm_table; multiboot_uint32_t apm_table;
/* Video */ /* Video */
multiboot_uint32_t vbe_control_info; multiboot_uint32_t vbe_control_info;
multiboot_uint32_t vbe_mode_info; multiboot_uint32_t vbe_mode_info;
multiboot_uint16_t vbe_mode; multiboot_uint16_t vbe_mode;
multiboot_uint16_t vbe_interface_seg; multiboot_uint16_t vbe_interface_seg;
multiboot_uint16_t vbe_interface_off; multiboot_uint16_t vbe_interface_off;
multiboot_uint16_t vbe_interface_len; multiboot_uint16_t vbe_interface_len;
multiboot_uint64_t framebuffer_addr; multiboot_uint64_t framebuffer_addr;
multiboot_uint32_t framebuffer_pitch; multiboot_uint32_t framebuffer_pitch;
multiboot_uint32_t framebuffer_width; multiboot_uint32_t framebuffer_width;
multiboot_uint32_t framebuffer_height; multiboot_uint32_t framebuffer_height;
multiboot_uint8_t framebuffer_bpp; multiboot_uint8_t framebuffer_bpp;
#define MULTIBOOT_FRAMEBUFFER_TYPE_INDEXED 0 #define MULTIBOOT_FRAMEBUFFER_TYPE_INDEXED 0
#define MULTIBOOT_FRAMEBUFFER_TYPE_RGB 1 #define MULTIBOOT_FRAMEBUFFER_TYPE_RGB 1
#define MULTIBOOT_FRAMEBUFFER_TYPE_EGA_TEXT 2 #define MULTIBOOT_FRAMEBUFFER_TYPE_EGA_TEXT 2
multiboot_uint8_t framebuffer_type; multiboot_uint8_t framebuffer_type;
union { union {
struct { struct {
multiboot_uint32_t framebuffer_palette_addr; multiboot_uint32_t framebuffer_palette_addr;
multiboot_uint16_t framebuffer_palette_num_colors; multiboot_uint16_t framebuffer_palette_num_colors;
};
struct {
multiboot_uint8_t framebuffer_red_field_position;
multiboot_uint8_t framebuffer_red_mask_size;
multiboot_uint8_t framebuffer_green_field_position;
multiboot_uint8_t framebuffer_green_mask_size;
multiboot_uint8_t framebuffer_blue_field_position;
multiboot_uint8_t framebuffer_blue_mask_size;
};
}; };
struct {
multiboot_uint8_t framebuffer_red_field_position;
multiboot_uint8_t framebuffer_red_mask_size;
multiboot_uint8_t framebuffer_green_field_position;
multiboot_uint8_t framebuffer_green_mask_size;
multiboot_uint8_t framebuffer_blue_field_position;
multiboot_uint8_t framebuffer_blue_mask_size;
};
};
}; };
typedef struct multiboot_info multiboot_info_t; typedef struct multiboot_info multiboot_info_t;
struct multiboot_color { struct multiboot_color {
multiboot_uint8_t red; multiboot_uint8_t red;
multiboot_uint8_t green; multiboot_uint8_t green;
multiboot_uint8_t blue; multiboot_uint8_t blue;
}; };
struct multiboot_mmap_entry { struct multiboot_mmap_entry {
multiboot_uint32_t size; multiboot_uint32_t size;
multiboot_uint64_t addr; multiboot_uint64_t addr;
multiboot_uint64_t len; multiboot_uint64_t len;
#define MULTIBOOT_MEMORY_AVAILABLE 1 #define MULTIBOOT_MEMORY_AVAILABLE 1
#define MULTIBOOT_MEMORY_RESERVED 2 #define MULTIBOOT_MEMORY_RESERVED 2
#define MULTIBOOT_MEMORY_ACPI_RECLAIMABLE 3 #define MULTIBOOT_MEMORY_ACPI_RECLAIMABLE 3
#define MULTIBOOT_MEMORY_NVS 4 #define MULTIBOOT_MEMORY_NVS 4
#define MULTIBOOT_MEMORY_BADRAM 5 #define MULTIBOOT_MEMORY_BADRAM 5
multiboot_uint32_t type; multiboot_uint32_t type;
} __attribute__((packed)); } __attribute__((packed));
typedef struct multiboot_mmap_entry multiboot_memory_map_t; typedef struct multiboot_mmap_entry multiboot_memory_map_t;
struct multiboot_mod_list { struct multiboot_mod_list {
/* the memory used goes from bytes 'mod_start' to 'mod_end-1' inclusive */ /* the memory used goes from bytes 'mod_start' to 'mod_end-1' inclusive */
multiboot_uint32_t mod_start; multiboot_uint32_t mod_start;
multiboot_uint32_t mod_end; multiboot_uint32_t mod_end;
/* Module command line */ /* Module command line */
multiboot_uint32_t cmdline; multiboot_uint32_t cmdline;
/* padding to take it to 16 bytes (must be zero) */ /* padding to take it to 16 bytes (must be zero) */
multiboot_uint32_t pad; multiboot_uint32_t pad;
}; };
typedef struct multiboot_mod_list multiboot_module_t; typedef struct multiboot_mod_list multiboot_module_t;
/* APM BIOS info. */ /* APM BIOS info. */
struct multiboot_apm_info { struct multiboot_apm_info {
multiboot_uint16_t version; multiboot_uint16_t version;
multiboot_uint16_t cseg; multiboot_uint16_t cseg;
multiboot_uint32_t offset; multiboot_uint32_t offset;
multiboot_uint16_t cseg_16; multiboot_uint16_t cseg_16;
multiboot_uint16_t dseg; multiboot_uint16_t dseg;
multiboot_uint16_t flags; multiboot_uint16_t flags;
multiboot_uint16_t cseg_len; multiboot_uint16_t cseg_len;
multiboot_uint16_t cseg_16_len; multiboot_uint16_t cseg_16_len;
multiboot_uint16_t dseg_len; multiboot_uint16_t dseg_len;
}; };
#endif /* ! ASM_FILE */ #endif /* ! ASM_FILE */

View File

@ -26,181 +26,179 @@
static unsigned long mappedPage = 0; static unsigned long mappedPage = 0;
struct pde { struct pde {
uint32_t present : 1; uint32_t present : 1;
uint32_t write : 1; // 0 read - 1 RW uint32_t write : 1; // 0 read - 1 RW
uint32_t user : 1; // 0 supervisor - 1 user uint32_t user : 1; // 0 supervisor - 1 user
uint32_t write_through : 1; // 0 write-back - 1 write_through uint32_t write_through : 1; // 0 write-back - 1 write_through
uint32_t cache_disable : 1; uint32_t cache_disable : 1;
uint32_t access : 1; // have been accessed uint32_t access : 1; // have been accessed
uint32_t zero : 1; // Not used uint32_t zero : 1; // Not used
uint32_t size : 1; // 0 for 4Kb 1 for 4Mb uint32_t size : 1; // 0 for 4Kb 1 for 4Mb
uint32_t ignored : 1; uint32_t ignored : 1;
uint32_t available : 3; uint32_t available : 3;
uint32_t pt_addr : 20; uint32_t pt_addr : 20;
} __attribute__((packed)); } __attribute__((packed));
struct pte { struct pte {
uint32_t present : 1; uint32_t present : 1;
uint32_t write : 1; // 0 read - 1 RW uint32_t write : 1; // 0 read - 1 RW
uint32_t user : 1; // 0 supervisor - 1 user uint32_t user : 1; // 0 supervisor - 1 user
uint32_t write_through : 1; // 0 write-back - 1 write_through uint32_t write_through : 1; // 0 write-back - 1 write_through
uint32_t cache_disable : 1; uint32_t cache_disable : 1;
uint32_t access : 1; // have been accessed uint32_t access : 1; // have been accessed
uint32_t dirty : 1; // if set, indicates that page has been written to. This flag is uint32_t dirty : 1; // if set, indicates that page has been written to. This flag is
// not updated by the CPU, and once set will not unset itself. // not updated by the CPU, and once set will not unset itself.
uint32_t zero : 1; // if PAT is supported, shall indicate the memory type. Otherwise, uint32_t zero : 1; // if PAT is supported, shall indicate the memory type. Otherwise,
// it must be 0. // it must be 0.
uint32_t global : 1; // if set, prevents the TLB from updating the address in its cache uint32_t global : 1; // if set, prevents the TLB from updating the address in its cache
// if CR3 is reset. Note, that the page global enable bit in CR4 // if CR3 is reset. Note, that the page global enable bit in CR4
// must be set to enable this feature. // must be set to enable this feature.
uint32_t available : 3; uint32_t available : 3;
uint32_t paddr : 20; uint32_t paddr : 20;
} __attribute__((packed)); } __attribute__((packed));
struct pdbr { struct pdbr {
uint32_t zero1 : 3; // reserved uint32_t zero1 : 3; // reserved
uint32_t write_through : 1; // 0 write-back - 1 write-through uint32_t write_through : 1; // 0 write-back - 1 write-through
uint32_t cache_disabled : 1; // 1=cache disabled uint32_t cache_disabled : 1; // 1=cache disabled
uint32_t zero2 : 7; // reserved uint32_t zero2 : 7; // reserved
uint32_t pd_paddr : 20; uint32_t pd_paddr : 20;
} __attribute__((packed)); } __attribute__((packed));
// invalidate the TLB entry for the page located at the given virtual address // invalidate the TLB entry for the page located at the given virtual address
static inline void __native_flush_tlb_single(unsigned long addr) static inline void __native_flush_tlb_single(unsigned long addr)
{ {
asm volatile("invlpg (%0)" ::"r"(addr) : "memory"); asm volatile("invlpg (%0)" ::"r"(addr) : "memory");
} }
int pagingSetup(paddr_t upperKernelAddr) int pagingSetup(paddr_t upperKernelAddr)
{ {
struct pdbr cr3; struct pdbr cr3;
// x86 got 1024 of pde for 4Byte each: 4ko ! // x86 got 1024 of pde for 4Byte each: 4ko !
struct pde *pd = (struct pde *)allocPhyPage(); struct pde *pd = (struct pde *)allocPhyPage();
memset(pd, 0, PAGE_SIZE); memset(pd, 0, PAGE_SIZE);
memset(&cr3, 0x0, sizeof(struct pdbr)); memset(&cr3, 0x0, sizeof(struct pdbr));
cr3.pd_paddr = ((paddr_t)pd) >> 12; cr3.pd_paddr = ((paddr_t)pd) >> 12;
// MMU not enabled for the moment. No need to use mirroring // MMU not enabled for the moment. No need to use mirroring
// Identity mapping up to upperKernelAddr // Identity mapping up to upperKernelAddr
for (paddr_t i = 0; i < upperKernelAddr; i += PAGE_SIZE) { for (paddr_t i = 0; i < upperKernelAddr; i += PAGE_SIZE) {
uint pdEntry = i >> (PD_SHIFT); uint pdEntry = i >> (PD_SHIFT);
uint ptEntry = (i >> PT_SHIFT) & PTE_MASK; uint ptEntry = (i >> PT_SHIFT) & PTE_MASK;
struct pte *pt; struct pte *pt;
if (pd[pdEntry].present) { if (pd[pdEntry].present) {
pt = (struct pte *)(pd[pdEntry].pt_addr << PT_SHIFT); pt = (struct pte *)(pd[pdEntry].pt_addr << PT_SHIFT);
refPhyPage((paddr_t)pt); refPhyPage((paddr_t)pt);
} else { } else {
pt = (struct pte *)allocPhyPage(); pt = (struct pte *)allocPhyPage();
memset(pt, 0, PAGE_SIZE); memset(pt, 0, PAGE_SIZE);
pd[pdEntry].present = 1; pd[pdEntry].present = 1;
pd[pdEntry].write = 1; pd[pdEntry].write = 1;
pd[pdEntry].pt_addr = ((paddr_t)pt >> PT_SHIFT); pd[pdEntry].pt_addr = ((paddr_t)pt >> PT_SHIFT);
} }
pt[ptEntry].present = 1; pt[ptEntry].present = 1;
pt[ptEntry].write = 1; // TODO set Kernel code as RO pt[ptEntry].write = 1; // TODO set Kernel code as RO
pt[ptEntry].paddr = i >> PAGE_SHIFT; pt[ptEntry].paddr = i >> PAGE_SHIFT;
} }
// Setup mirroring // Setup mirroring
pd[PD_MIRROR_PAGE_IDX].present = 1; pd[PD_MIRROR_PAGE_IDX].present = 1;
pd[PD_MIRROR_PAGE_IDX].write = 1; pd[PD_MIRROR_PAGE_IDX].write = 1;
pd[PD_MIRROR_PAGE_IDX].pt_addr = ((paddr_t)pd >> PT_SHIFT); pd[PD_MIRROR_PAGE_IDX].pt_addr = ((paddr_t)pd >> PT_SHIFT);
// Loading of the PDBR in the MMU: // Loading of the PDBR in the MMU:
asm volatile("movl %0,%%cr3\n\t" asm volatile("movl %0,%%cr3\n\t"
"movl %%cr0,%%eax\n\t" "movl %%cr0,%%eax\n\t"
"orl $0x80010000, %%eax\n\t" /* bit 31 | bit 16 */ "orl $0x80010000, %%eax\n\t" /* bit 31 | bit 16 */
"movl %%eax,%%cr0\n\t" "movl %%eax,%%cr0\n\t"
"jmp 1f\n\t" "jmp 1f\n\t"
"1:\n\t" "1:\n\t"
"movl $2f, %%eax\n\t" "movl $2f, %%eax\n\t"
"jmp *%%eax\n\t" "jmp *%%eax\n\t"
"2:\n\t" ::"r"(cr3) "2:\n\t" ::"r"(cr3)
: "memory", "eax"); : "memory", "eax");
return 0; return 0;
} }
int pageMap(vaddr_t vaddr, paddr_t paddr, int flags) int pageMap(vaddr_t vaddr, paddr_t paddr, int flags)
{ {
uint pdEntry = vaddr >> (PD_SHIFT); uint pdEntry = vaddr >> (PD_SHIFT);
uint ptEntry = (vaddr >> PT_SHIFT) & PTE_MASK; uint ptEntry = (vaddr >> PT_SHIFT) & PTE_MASK;
// Thank to mirroring, we can access the PD // Thank to mirroring, we can access the PD
struct pde *pd = (struct pde *)((PD_MIRROR_PAGE_IDX << PD_SHIFT) + struct pde *pd =
(PD_MIRROR_PAGE_IDX << PT_SHIFT)); (struct pde *)((PD_MIRROR_PAGE_IDX << PD_SHIFT) + (PD_MIRROR_PAGE_IDX << PT_SHIFT));
struct pte *pt = struct pte *pt = (struct pte *)((PD_MIRROR_PAGE_IDX << PD_SHIFT) + (pdEntry << PT_SHIFT));
(struct pte *)((PD_MIRROR_PAGE_IDX << PD_SHIFT) + (pdEntry << PT_SHIFT));
if (!pd[pdEntry].present) { if (!pd[pdEntry].present) {
paddr_t ptPhy = allocPhyPage(); paddr_t ptPhy = allocPhyPage();
if (ptPhy == (vaddr_t)NULL) if (ptPhy == (vaddr_t)NULL)
return -ENOMEM; return -ENOMEM;
pd[pdEntry].user = (flags & PAGING_MEM_USER) ? 1 : 0; pd[pdEntry].user = (flags & PAGING_MEM_USER) ? 1 : 0;
pd[pdEntry].present = 1; pd[pdEntry].present = 1;
pd[pdEntry].write = 1; pd[pdEntry].write = 1;
pd[pdEntry].pt_addr = (ptPhy >> PT_SHIFT); pd[pdEntry].pt_addr = (ptPhy >> PT_SHIFT);
__native_flush_tlb_single((vaddr_t)pt); __native_flush_tlb_single((vaddr_t)pt);
memset((void *)pt, 0, PAGE_SIZE); memset((void *)pt, 0, PAGE_SIZE);
} else { } else {
// Already mapped ? Remove old mapping // Already mapped ? Remove old mapping
if (pt[ptEntry].present) { if (pt[ptEntry].present) {
unrefPhyPage(pt[ptEntry].paddr << PAGE_SHIFT); unrefPhyPage(pt[ptEntry].paddr << PAGE_SHIFT);
} // PTE not already used ? We will use it ! So increase the PT ref count } // PTE not already used ? We will use it ! So increase the PT ref count
else { else {
refPhyPage(pd[pdEntry].pt_addr << PAGE_SHIFT); refPhyPage(pd[pdEntry].pt_addr << PAGE_SHIFT);
} }
} }
pt[ptEntry].user = (flags & PAGING_MEM_USER) ? 1 : 0; pt[ptEntry].user = (flags & PAGING_MEM_USER) ? 1 : 0;
pt[ptEntry].present = 1; pt[ptEntry].present = 1;
pt[ptEntry].write = (flags & PAGING_MEM_WRITE) ? 1 : 0; pt[ptEntry].write = (flags & PAGING_MEM_WRITE) ? 1 : 0;
pt[ptEntry].paddr = paddr >> PAGE_SHIFT; pt[ptEntry].paddr = paddr >> PAGE_SHIFT;
refPhyPage(paddr); refPhyPage(paddr);
__native_flush_tlb_single(vaddr); __native_flush_tlb_single(vaddr);
mappedPage++; mappedPage++;
return 0; return 0;
} }
int pageUnmap(vaddr_t vaddr) int pageUnmap(vaddr_t vaddr)
{ {
uint pdEntry = vaddr >> (PD_SHIFT); uint pdEntry = vaddr >> (PD_SHIFT);
uint ptEntry = (vaddr >> PT_SHIFT) & PTE_MASK; uint ptEntry = (vaddr >> PT_SHIFT) & PTE_MASK;
// Thank to mirroring, we can access the PD // Thank to mirroring, we can access the PD
struct pde *pd = (struct pde *)((PD_MIRROR_PAGE_IDX << PD_SHIFT) + struct pde *pd =
(PD_MIRROR_PAGE_IDX << PT_SHIFT)); (struct pde *)((PD_MIRROR_PAGE_IDX << PD_SHIFT) + (PD_MIRROR_PAGE_IDX << PT_SHIFT));
struct pte *pt = struct pte *pt = (struct pte *)((PD_MIRROR_PAGE_IDX << PD_SHIFT) + (pdEntry << PT_SHIFT));
(struct pte *)((PD_MIRROR_PAGE_IDX << PD_SHIFT) + (pdEntry << PT_SHIFT)); if (!pd[pdEntry].present)
if (!pd[pdEntry].present) return -EINVAL;
return -EINVAL; if (!pt[ptEntry].present)
if (!pt[ptEntry].present) return -EINVAL;
return -EINVAL;
unrefPhyPage(pt[ptEntry].paddr << PAGE_SHIFT); unrefPhyPage(pt[ptEntry].paddr << PAGE_SHIFT);
pt[ptEntry].present = 0; pt[ptEntry].present = 0;
// PTE not used. Decrease refcount on it. Is PT not used anymore ? // PTE not used. Decrease refcount on it. Is PT not used anymore ?
if (unrefPhyPage(pd[pdEntry].pt_addr << PT_SHIFT) == 0) { if (unrefPhyPage(pd[pdEntry].pt_addr << PT_SHIFT) == 0) {
pd[pdEntry].present = 0; pd[pdEntry].present = 0;
__native_flush_tlb_single((vaddr_t)pt); __native_flush_tlb_single((vaddr_t)pt);
} }
__native_flush_tlb_single(vaddr); __native_flush_tlb_single(vaddr);
mappedPage--; mappedPage--;
return 0; return 0;
} }
unsigned long getNbMappedPage(void) unsigned long getNbMappedPage(void)
{ {
return mappedPage; return mappedPage;
} }

View File

@ -5,16 +5,16 @@
modify it under the terms of the GNU General Public License modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2 as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version. of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
USA. USA.
*/ */
#pragma once #pragma once
@ -36,19 +36,15 @@
* *
* @see gdt.h * @see gdt.h
*/ */
#define SEG_NULL 0 /* NULL segment, unused by the procesor */ #define SEG_NULL 0 /* NULL segment, unused by the procesor */
#define SEG_KCODE 1 /* Kernel code segment */ #define SEG_KCODE 1 /* Kernel code segment */
#define SEG_KDATA 2 /* Kernel data segment */ #define SEG_KDATA 2 /* Kernel data segment */
/** /**
* Helper macro that builds a segment register's value * Helper macro that builds a segment register's value
*/ */
#define BUILD_SEGMENT_REG_VALUE(desc_privilege,in_ldt,seg_index) \ #define BUILD_SEGMENT_REG_VALUE(desc_privilege, in_ldt, seg_index) \
( (((desc_privilege) & 0x3) << 0) \ ((((desc_privilege)&0x3) << 0) | (((in_ldt) ? 1 : 0) << 2) | ((seg_index) << 3))
| (((in_ldt)?1:0) << 2) \
| ((seg_index) << 3) )
/* /*
* Local segment selectors (LDT) for SOS/x86 * Local segment selectors (LDT) for SOS/x86

View File

@ -1,48 +1,47 @@
#include "stack.h" #include "stack.h"
#include "types.h"
#include "klibc.h" #include "klibc.h"
#include "types.h"
void printStackTrace(unsigned int maxFrames) void printStackTrace(unsigned int maxFrames)
{ {
#ifdef DEBUG #ifdef DEBUG
// Now on Stack: // Now on Stack:
// ( potential second function argument ) // ( potential second function argument )
// first function argument (maxFrames) // first function argument (maxFrames)
// return address from caller // return address from caller
// EBP (Extended Base Pointer) of calling function // EBP (Extended Base Pointer) of calling function
// //
// retrace function from address could done by optaining function address with gdb or // retrace function from address could done by optaining function address with gdb or
// objdump -S kernel // objdump -S kernel
unsigned int *ebp = __builtin_frame_address(0); unsigned int *ebp = __builtin_frame_address(0);
for (unsigned int frame = 0; frame < maxFrames; frame++) { for (unsigned int frame = 0; frame < maxFrames; frame++) {
unsigned int eip = ebp[1]; unsigned int eip = ebp[1];
if (eip == 0) { if (eip == 0) {
// No caller on stack // No caller on stack
break; break;
} }
unsigned int *arguments = ebp + 2; unsigned int *arguments = ebp + 2;
printf("[%d] 0x%x (", frame, eip); printf("[%d] 0x%x (", frame, eip);
int nbArg = 0; int nbArg = 0;
do { do {
if ((_stack_bottom <= (vaddr_t)arguments) && if ((_stack_bottom <= (vaddr_t)arguments) && ((vaddr_t)arguments <= _stack_top)) {
((vaddr_t)arguments <= _stack_top)) { printf(" 0x%x", *arguments);
printf(" 0x%x", *arguments); arguments += 1;
arguments += 1; } else {
} else { break;
break; }
} nbArg++;
nbArg++; if (nbArg >= 4) {
if (nbArg >= 4) { break;
break; }
} } while (1);
} while (1); printf(")\n");
printf(")\n"); ebp = (unsigned int *)(ebp[0]);
ebp = (unsigned int *)(ebp[0]); }
}
#else #else
printf("Must be compiled with -fno-omit-frame-pointer for full stack\n"); printf("Must be compiled with -fno-omit-frame-pointer for full stack\n");
unsigned int *ebp = &maxFrames - 2; unsigned int *ebp = &maxFrames - 2;
unsigned int eip = ebp[1]; unsigned int eip = ebp[1];
printf("[0] 0x%x\n", eip); printf("[0] 0x%x\n", eip);
#endif #endif
} }

View File

@ -18,37 +18,37 @@ typedef unsigned long long __u64;
#endif #endif
/* sysv */ /* sysv */
typedef unsigned char unchar; typedef unsigned char unchar;
typedef unsigned short ushort; typedef unsigned short ushort;
typedef unsigned int uint; typedef unsigned int uint;
typedef unsigned long ulong; typedef unsigned long ulong;
typedef __s8 int8_t; typedef __s8 int8_t;
typedef __s16 int16_t; typedef __s16 int16_t;
typedef __s32 int32_t; typedef __s32 int32_t;
typedef __u8 uint8_t; typedef __u8 uint8_t;
typedef __u16 uint16_t; typedef __u16 uint16_t;
typedef __u32 uint32_t; typedef __u32 uint32_t;
typedef __u64 uint64_t; typedef __u64 uint64_t;
typedef __u64 u_int64_t; typedef __u64 u_int64_t;
typedef __s64 int64_t; typedef __s64 int64_t;
typedef enum { FALSE=0, TRUE } bool_t; typedef enum { FALSE = 0, TRUE } bool_t;
#define NULL ((void*)0) #define NULL ((void *)0)
#if __x86_64__ #if __x86_64__
typedef unsigned long size_t; typedef unsigned long size_t;
typedef long ssize_t; typedef long ssize_t;
typedef unsigned long int uintptr_t; typedef unsigned long int uintptr_t;
#else #else
typedef unsigned int size_t; typedef unsigned int size_t;
typedef int ssize_t; typedef int ssize_t;
typedef unsigned int uintptr_t; typedef unsigned int uintptr_t;
#endif #endif
typedef void *va_list; typedef void *va_list;
#define va_start(v, l) ((v) = (va_list) & (l) + sizeof(l)) #define va_start(v, l) ((v) = (va_list) & (l) + sizeof(l))
#define va_end(v) ((v) = NULL) #define va_end(v) ((v) = NULL)
#define va_arg(v, type) (*(type *)(((v)+=sizeof(type))-sizeof(type))) #define va_arg(v, type) (*(type *)(((v) += sizeof(type)) - sizeof(type)))

View File

@ -1,32 +1,32 @@
#pragma once #pragma once
#define USHRT_MAX ((u16)(~0U)) #define USHRT_MAX ((u16)(~0U))
#define SHRT_MAX ((s16)(USHRT_MAX>>1)) #define SHRT_MAX ((s16)(USHRT_MAX >> 1))
#define SHRT_MIN ((s16)(-SHRT_MAX - 1)) #define SHRT_MIN ((s16)(-SHRT_MAX - 1))
#define INT_MAX ((int)(~0U>>1)) #define INT_MAX ((int)(~0U >> 1))
#define INT_MIN (-INT_MAX - 1) #define INT_MIN (-INT_MAX - 1)
#define UINT_MAX (~0U) #define UINT_MAX (~0U)
#define LONG_MAX ((long)(~0UL>>1)) #define LONG_MAX ((long)(~0UL >> 1))
#define LONG_MIN (-LONG_MAX - 1) #define LONG_MIN (-LONG_MAX - 1)
#define ULONG_MAX (~0UL) #define ULONG_MAX (~0UL)
#define LLONG_MAX ((long long)(~0ULL>>1)) #define LLONG_MAX ((long long)(~0ULL >> 1))
#define LLONG_MIN (-LLONG_MAX - 1) #define LLONG_MIN (-LLONG_MAX - 1)
#define ULLONG_MAX (~0ULL) #define ULLONG_MAX (~0ULL)
#define SIZE_MAX (~(size_t)0) #define SIZE_MAX (~(size_t)0)
#define PHYS_ADDR_MAX (~(phys_addr_t)0) #define PHYS_ADDR_MAX (~(phys_addr_t)0)
#define U8_MAX ((u8)~0U) #define U8_MAX ((u8)~0U)
#define S8_MAX ((s8)(U8_MAX>>1)) #define S8_MAX ((s8)(U8_MAX >> 1))
#define S8_MIN ((s8)(-S8_MAX - 1)) #define S8_MIN ((s8)(-S8_MAX - 1))
#define U16_MAX ((u16)~0U) #define U16_MAX ((u16)~0U)
#define S16_MAX ((s16)(U16_MAX>>1)) #define S16_MAX ((s16)(U16_MAX >> 1))
#define S16_MIN ((s16)(-S16_MAX - 1)) #define S16_MIN ((s16)(-S16_MAX - 1))
#define U32_MAX ((u32)~0U) #define U32_MAX ((u32)~0U)
#define S32_MAX ((s32)(U32_MAX>>1)) #define S32_MAX ((s32)(U32_MAX >> 1))
#define S32_MIN ((s32)(-S32_MAX - 1)) #define S32_MIN ((s32)(-S32_MAX - 1))
#define U64_MAX ((u64)~0ULL) #define U64_MAX ((u64)~0ULL)
#define S64_MAX ((s64)(U64_MAX>>1)) #define S64_MAX ((s64)(U64_MAX >> 1))
#define S64_MIN ((s64)(-S64_MAX - 1)) #define S64_MIN ((s64)(-S64_MAX - 1))
#define __ALIGN_KERNEL(x, a) __ALIGN_KERNEL_MASK(x, (typeof(x))(a)-1) #define __ALIGN_KERNEL(x, a) __ALIGN_KERNEL_MASK(x, (typeof(x))(a)-1)
#define __ALIGN_KERNEL_MASK(x, mask) (((x) + (mask)) & ~(mask)) #define __ALIGN_KERNEL_MASK(x, mask) (((x) + (mask)) & ~(mask))

View File

@ -1,6 +1,6 @@
#include "keyboard.h" #include "keyboard.h"
#include "klibc.h"
#include "io.h" #include "io.h"
#include "klibc.h"
const char *scancode[128] = { const char *scancode[128] = {
/* 0 */ 0, /* 0 */ 0,
@ -61,7 +61,7 @@ const char *scancode[128] = {
/* 55 */ "*", /* 55 */ "*",
/* 56 */ 0, /* left alt*/ /* 56 */ 0, /* left alt*/
/* 57 */ " ", /* 57 */ " ",
/* 58 */ 0, /* caps Lock */ /* 58 */ 0, /* caps Lock */
/* 59 */ "\eOP", /* F1 */ /* 59 */ "\eOP", /* F1 */
/* 60 */ "\eOQ", /* F2 */ /* 60 */ "\eOQ", /* F2 */
/* 61 */ "\eOR", /* F3 */ /* 61 */ "\eOR", /* F3 */
@ -72,7 +72,7 @@ const char *scancode[128] = {
/* 66 */ "\e[19~", /* F8 */ /* 66 */ "\e[19~", /* F8 */
/* 67 */ "\e[20~", /* F9 */ /* 67 */ "\e[20~", /* F9 */
/* 68 */ "\e[21~", /* F10 */ /* 68 */ "\e[21~", /* F10 */
/* 69 */ 0, /* VerrNum*/ /* 69 */ 0, /* VerrNum*/
/* 70 */ 0, /* 70 */ 0,
/* 71 */ "7", /* 71 */ "7",
/* 72 */ "8", /* 72 */ "8",
@ -264,50 +264,50 @@ const char *scancode_shift[128] = {
void keyboard_do_irq() void keyboard_do_irq()
{ {
static int lshift = 0; static int lshift = 0;
static int rshift = 0; static int rshift = 0;
static int capslock = 0; static int capslock = 0;
static int isExt = 0; static int isExt = 0;
unsigned char c = inb(KEYBOARD_DATA_PORT); unsigned char c = inb(KEYBOARD_DATA_PORT);
const char *key = NULL; const char *key = NULL;
if (c > 0) { if (c > 0) {
if (c == 0xE0) { // non printable such as page up/down ... See https://wiki.osdev.org/Keyboard if (c == 0xE0) { // non printable such as page up/down ... See
isExt = 1; // https://wiki.osdev.org/Keyboard
} else if (isExt) { isExt = 1;
isExt = 0; } else if (isExt) {
return; isExt = 0;
} return;
if (c < BREAK_CODE) { }
switch (c) { if (c < BREAK_CODE) {
case 42: switch (c) {
lshift = 1; case 42:
break; lshift = 1;
case 54: break;
rshift = 1; case 54:
break; rshift = 1;
case 58: break;
capslock = 1 - capslock; case 58:
break; capslock = 1 - capslock;
default: break;
if ((lshift || rshift) ^ capslock) { default:
key = scancode_shift[(int)c]; if ((lshift || rshift) ^ capslock) {
} else { key = scancode_shift[(int)c];
key = scancode[(int)c]; } else {
} key = scancode[(int)c];
} }
} else { }
c = c - BREAK_CODE; } else {
switch (c) { c = c - BREAK_CODE;
case 42: switch (c) {
lshift = 0; case 42:
break; lshift = 0;
case 54: break;
rshift = 0; case 54:
} rshift = 0;
} }
} }
}
if (key) if (key)
printf(key); printf(key);
} }

View File

@ -16,58 +16,58 @@
void initPic(void) void initPic(void)
{ {
/* Send CMD: Init + sequence in 4 DATA */ /* Send CMD: Init + sequence in 4 DATA */
outb(PIC_MASTER_CMD, ICW1_INIT + ICW1_ICW4); outb(PIC_MASTER_CMD, ICW1_INIT + ICW1_ICW4);
outb(PIC_SLAVE_CMD, ICW1_INIT + ICW1_ICW4); outb(PIC_SLAVE_CMD, ICW1_INIT + ICW1_ICW4);
/* Send ICW2: ctrl base address. Remap IRQ from interupt range 0x0-0xF to 0x20-0x2F as /* Send ICW2: ctrl base address. Remap IRQ from interupt range 0x0-0xF to 0x20-0x2F as
* intel * intel
* reserve interupt 0x0-0x1F in protected mode (e.g. 0-7 are CPU exception) */ * reserve interupt 0x0-0x1F in protected mode (e.g. 0-7 are CPU exception) */
outb(PIC_MASTER_DATA, IRQ_INTERRUPT_BASE_ADDRESS); outb(PIC_MASTER_DATA, IRQ_INTERRUPT_BASE_ADDRESS);
outb(PIC_SLAVE_DATA, IRQ_INTERRUPT_BASE_ADDRESS + 8); outb(PIC_SLAVE_DATA, IRQ_INTERRUPT_BASE_ADDRESS + 8);
/* Send ICW3 master: mask where slaves are connected */ /* Send ICW3 master: mask where slaves are connected */
outb(PIC_MASTER_DATA, 0x4); outb(PIC_MASTER_DATA, 0x4);
/* Send ICW3 slave: index where the slave is connected on master */ /* Send ICW3 slave: index where the slave is connected on master */
outb(PIC_SLAVE_DATA, 0x2); outb(PIC_SLAVE_DATA, 0x2);
/* Send ICW4: 8086 mode, fully nested, not buffered, no implicit EOI */ /* Send ICW4: 8086 mode, fully nested, not buffered, no implicit EOI */
outb(PIC_MASTER_DATA, ICW4_8086); outb(PIC_MASTER_DATA, ICW4_8086);
outb(PIC_SLAVE_DATA, ICW4_8086); outb(PIC_SLAVE_DATA, ICW4_8086);
/* Send OCW1: /* Send OCW1:
* Closing all IRQs : waiting for a correct handler The only IRQ * Closing all IRQs : waiting for a correct handler The only IRQ
* enabled is the cascade (that's why we use 0xFB for the master) */ * enabled is the cascade (that's why we use 0xFB for the master) */
outb(PIC_MASTER_DATA, 0xFB); outb(PIC_MASTER_DATA, 0xFB);
outb(PIC_SLAVE_DATA, 0xFF); outb(PIC_SLAVE_DATA, 0xFF);
} }
void EOIIrq(int irq) void EOIIrq(int irq)
{ {
if (irq >= 8) if (irq >= 8)
outb(PIC_SLAVE_CMD, PIC_EOI); outb(PIC_SLAVE_CMD, PIC_EOI);
outb(PIC_MASTER_CMD, PIC_EOI); outb(PIC_MASTER_CMD, PIC_EOI);
} }
void disableIrq(int irq) void disableIrq(int irq)
{ {
if (irq < 8) { if (irq < 8) {
uint8_t status = inb(PIC_MASTER_DATA); uint8_t status = inb(PIC_MASTER_DATA);
outb(PIC_MASTER_DATA, (status | (1 << irq))); outb(PIC_MASTER_DATA, (status | (1 << irq)));
} else { } else {
uint8_t status = inb(PIC_SLAVE_DATA); uint8_t status = inb(PIC_SLAVE_DATA);
outb(PIC_SLAVE_DATA, (status | (1 << (irq - 8)))); outb(PIC_SLAVE_DATA, (status | (1 << (irq - 8))));
} }
} }
void enableIrq(int irq) void enableIrq(int irq)
{ {
if (irq < 8) { if (irq < 8) {
uint8_t status = inb(PIC_MASTER_DATA); uint8_t status = inb(PIC_MASTER_DATA);
outb(PIC_MASTER_DATA, (status & ~(1 << irq))); outb(PIC_MASTER_DATA, (status & ~(1 << irq)));
} else { } else {
uint8_t status = inb(PIC_SLAVE_DATA); uint8_t status = inb(PIC_SLAVE_DATA);
outb(PIC_SLAVE_DATA, (status & ~(1 << (irq - 8)))); outb(PIC_SLAVE_DATA, (status & ~(1 << (irq - 8))));
} }
} }

View File

@ -14,7 +14,6 @@
#define PIC_SLAVE_DATA 0xa1 #define PIC_SLAVE_DATA 0xa1
#define PIC_EOI 0x20 /* End-of-interrupt command code */ #define PIC_EOI 0x20 /* End-of-interrupt command code */
void EOIIrq(int irq); void EOIIrq(int irq);
void initPic(void); void initPic(void);
void enableIrq(int irq); void enableIrq(int irq);

View File

@ -4,12 +4,12 @@
int pitSetup(unsigned int freq) int pitSetup(unsigned int freq)
{ {
unsigned int divisor = PIT_FREQ / freq; unsigned int divisor = PIT_FREQ / freq;
if (divisor > 65535) if (divisor > 65535)
divisor = 0; // Used to represent 35536 divisor = 0; // Used to represent 35536
outb(PIT_CMD, 0x34); // chan 0; low then high; mode 2 outb(PIT_CMD, 0x34); // chan 0; low then high; mode 2
outb(PIT_CHAN_0, divisor & 0xFF); outb(PIT_CHAN_0, divisor & 0xFF);
outb(PIT_CHAN_0, divisor >> 8u); outb(PIT_CHAN_0, divisor >> 8u);
return 0; return 0;
} }

View File

@ -13,4 +13,3 @@
// 3 -> low then high 3-1: mode. See https://wiki.osdev.org/PIT // 3 -> low then high 3-1: mode. See https://wiki.osdev.org/PIT
int pitSetup(unsigned int freq); int pitSetup(unsigned int freq);

View File

@ -22,34 +22,35 @@
void serialSetup(int speed) void serialSetup(int speed)
{ {
unsigned short div = SERIAL_MAX_SPEED / speed; unsigned short div = SERIAL_MAX_SPEED / speed;
outb(PORT + 1, 0x00); // Disable all interrupts outb(PORT + 1, 0x00); // Disable all interrupts
outb(PORT + 3, 0x80); // Enable DLAB (set baud rate divisor) outb(PORT + 3, 0x80); // Enable DLAB (set baud rate divisor)
outb(PORT + 0, div & 0xFF); // Set divisor lo byte outb(PORT + 0, div & 0xFF); // Set divisor lo byte
outb(PORT + 1, div >> 8); // Set divisor hi byte outb(PORT + 1, div >> 8); // Set divisor hi byte
outb(PORT + 3, outb(PORT + 3,
UART_NO_PARITY | UART_8BITS_WORD | UART_1_STOP_BIT); // 8 bits, no parity, one stop bit UART_NO_PARITY | UART_8BITS_WORD |
outb(PORT + 2, 0xC7); // Enable FIFO, clear them, with 14-byte threshold UART_1_STOP_BIT); // 8 bits, no parity, one stop bit
outb(PORT + 4, 0x0B); // IRQs enabled, RTS/DSR set outb(PORT + 2, 0xC7); // Enable FIFO, clear them, with 14-byte threshold
irqSetRoutine(IRQ_COM1, serial_handler); outb(PORT + 4, 0x0B); // IRQs enabled, RTS/DSR set
irqSetRoutine(IRQ_COM1, serial_handler);
} }
int isTransmitEmpty() int isTransmitEmpty()
{ {
return (inb(PORT + 5) & 0x20); return (inb(PORT + 5) & 0x20);
} }
void serialPutc(char a) void serialPutc(char a)
{ {
while (isTransmitEmpty() == 0) while (isTransmitEmpty() == 0)
; ;
outb(PORT, a); outb(PORT, a);
} }
void serialDoIrq(struct interrupt_frame *level) void serialDoIrq(struct interrupt_frame *level)
{ {
(void)level; (void)level;
char c = inb(PORT); char c = inb(PORT);
serialPutc(c); serialPutc(c);
} }

View File

@ -8,146 +8,142 @@ static int line, col;
int VGASetup(uint bgColor, uint color) int VGASetup(uint bgColor, uint color)
{ {
vgaBgColor = bgColor; vgaBgColor = bgColor;
vgaColor = color; vgaColor = color;
clearScreen(bgColor); clearScreen(bgColor);
line = 0; line = 0;
col = 0; col = 0;
return 0; return 0;
} }
void clearScreen(uint bgColor) void clearScreen(uint bgColor)
{ {
volatile short *vga = (short *)VGA_ADDR; volatile short *vga = (short *)VGA_ADDR;
long int colorAttr = bgColor << 12; long int colorAttr = bgColor << 12;
for (int i = 0; i < VGA_WIDTH * VGA_HEIGHT; i++) { for (int i = 0; i < VGA_WIDTH * VGA_HEIGHT; i++) {
vga[i] = colorAttr; vga[i] = colorAttr;
} }
} }
void clearScreenLine(uint bgColor, uint line) void clearScreenLine(uint bgColor, uint line)
{ {
volatile short *vga = (short *)VGA_ADDR; volatile short *vga = (short *)VGA_ADDR;
long int colorAttr = bgColor << 12; long int colorAttr = bgColor << 12;
for (uint i = VGA_WIDTH * line; i < VGA_WIDTH * (line + 1); i++) { for (uint i = VGA_WIDTH * line; i < VGA_WIDTH * (line + 1); i++) {
vga[i] = colorAttr; vga[i] = colorAttr;
} }
} }
void printIntDetails(int integer, uint color, uint bgColor, int startX, int startY) void printIntDetails(int integer, uint color, uint bgColor, int startX, int startY)
{ {
char num[sizeof(int) * char num[sizeof(int) * 3]; // int max is 2^(sizeof(int)*8) which is (2^3)^(sizeof(int)*8/3)
3]; // int max is 2^(sizeof(int)*8) which is (2^3)^(sizeof(int)*8/3) = // = 8^(sizeof(int)*8/3) ~ 10^(sizeof(int)*8/3)
// 8^(sizeof(int)*8/3) ~ 10^(sizeof(int)*8/3) int x = startX;
int x = startX; int i = 0, k = 0;
int i = 0, k = 0; if (integer < 0) {
if (integer < 0) { printCharDetails('-', color, bgColor, x++, startY);
printCharDetails('-', color, bgColor, x++, startY); }
} if (integer == 0) {
if (integer == 0) { num[i++] = 0;
num[i++] = 0; }
} while (integer != 0) {
while (integer != 0) { int digit = integer % 10;
int digit = integer % 10; num[i++] = (digit > 0) ? digit : -digit;
num[i++] = (digit > 0) ? digit : -digit; integer = integer / 10;
integer = integer / 10; }
} for (k = i - 1; k >= 0; k--) {
for (k = i - 1; k >= 0; k--) { printCharDetails(num[k] + '0', color, bgColor, x++, startY);
printCharDetails(num[k] + '0', color, bgColor, x++, startY); }
}
} }
void printCharDetails(const char str, uint color, uint bgColor, int startX, int startY) void printCharDetails(const char str, uint color, uint bgColor, int startX, int startY)
{ {
volatile short *vga = (short *)VGA_ADDR; volatile short *vga = (short *)VGA_ADDR;
long int colorAttr = (bgColor << 4 | (color & 0x0f)) << 8; long int colorAttr = (bgColor << 4 | (color & 0x0f)) << 8;
vga[VGA_WIDTH * startY + startX] = colorAttr | str; vga[VGA_WIDTH * startY + startX] = colorAttr | str;
} }
void vgaScrollUp(void) void vgaScrollUp(void)
{ {
long int colorAttr = vgaBgColor << 12; long int colorAttr = vgaBgColor << 12;
volatile short *vga = (short *)VGA_ADDR; volatile short *vga = (short *)VGA_ADDR;
for (int i = 1; i < VGA_HEIGHT - 1; for (int i = 1; i < VGA_HEIGHT - 1; i++) { // last line is status line. Do not scroll it
i++) { // last line is status line. Do not scroll it memcpy((void *)&vga[VGA_WIDTH * (i - 1)], (void *)&vga[VGA_WIDTH * i],
memcpy((void *)&vga[VGA_WIDTH * (i - 1)], (void *)&vga[VGA_WIDTH * i], VGA_WIDTH * sizeof(short));
VGA_WIDTH * sizeof(short)); }
} for (int i = 0; i < VGA_WIDTH; i++) {
for (int i = 0; i < VGA_WIDTH; i++) { vga[(VGA_HEIGHT - 2) * VGA_WIDTH + i] = colorAttr;
vga[(VGA_HEIGHT - 2) * VGA_WIDTH + i] = colorAttr; }
}
} }
void VGAputc(const char str) void VGAputc(const char str)
{ {
if (str == '\n') { if (str == '\n') {
line++; line++;
col = 0; col = 0;
if (line >= VGA_HEIGHT - 1) { if (line >= VGA_HEIGHT - 1) {
vgaScrollUp(); vgaScrollUp();
line--; line--;
} }
} else if (str == '\r') { } else if (str == '\r') {
col = 0; col = 0;
} else if (str == '\b') { } else if (str == '\b') {
col--; col--;
if (col < 0) { if (col < 0) {
col = VGA_WIDTH - 1; col = VGA_WIDTH - 1;
line--; line--;
} }
printCharDetails(' ', vgaColor, vgaBgColor, col, line); printCharDetails(' ', vgaColor, vgaBgColor, col, line);
} else { } else {
printCharDetails(str, vgaColor, vgaBgColor, col++, line); printCharDetails(str, vgaColor, vgaBgColor, col++, line);
if (col == VGA_WIDTH) { if (col == VGA_WIDTH) {
col = 0; col = 0;
line++; line++;
} }
if (line >= VGA_HEIGHT - 1) { if (line >= VGA_HEIGHT - 1) {
vgaScrollUp(); vgaScrollUp();
line--; line--;
} }
} }
cursorMove(col, line); cursorMove(col, line);
} }
void printStringDetails(const char *str, uint color, uint bgColor, int startX, int startY) void printStringDetails(const char *str, uint color, uint bgColor, int startX, int startY)
{ {
volatile short *vga = (short *)VGA_ADDR; volatile short *vga = (short *)VGA_ADDR;
int i = 0; int i = 0;
long int colorAttr = (bgColor << 4 | (color & 0x0f)) << 8; long int colorAttr = (bgColor << 4 | (color & 0x0f)) << 8;
while (*str) { while (*str) {
vga[VGA_WIDTH * startY + startX + i] = colorAttr | *str; vga[VGA_WIDTH * startY + startX + i] = colorAttr | *str;
str++; str++;
i++; i++;
} }
} }
void cursorEnable(uint8_t cursor_start, uint8_t cursor_end) void cursorEnable(uint8_t cursor_start, uint8_t cursor_end)
{ {
outb(0x3D4, 0x0A); outb(0x3D4, 0x0A);
outb(0x3D5, (inb(0x3D5) & 0xC0) | cursor_start); outb(0x3D5, (inb(0x3D5) & 0xC0) | cursor_start);
outb(0x3D4, 0x0B); outb(0x3D4, 0x0B);
outb(0x3D5, (inb(0x3D5) & 0xE0) | cursor_end); outb(0x3D5, (inb(0x3D5) & 0xE0) | cursor_end);
} }
void cursorDisable(void) void cursorDisable(void)
{ {
outb(0x3D4, 0x0A); outb(0x3D4, 0x0A);
outb(0x3D5, 0x20); outb(0x3D5, 0x20);
} }
void cursorMove(int x, int y) void cursorMove(int x, int y)
{ {
volatile short *vga = (short *)VGA_ADDR; volatile short *vga = (short *)VGA_ADDR;
long int colorAttr = (vgaBgColor << 4 | (vgaColor & 0x0f)) << 8; long int colorAttr = (vgaBgColor << 4 | (vgaColor & 0x0f)) << 8;
uint16_t pos = y * VGA_WIDTH + x; uint16_t pos = y * VGA_WIDTH + x;
vga[pos] = colorAttr; vga[pos] = colorAttr;
outb(0x3D4, 0x0F); outb(0x3D4, 0x0F);
outb(0x3D5, (uint8_t)(pos & 0xFF)); outb(0x3D5, (uint8_t)(pos & 0xFF));
outb(0x3D4, 0x0E); outb(0x3D4, 0x0E);
outb(0x3D5, (uint8_t)((pos >> 8) & 0xFF)); outb(0x3D5, (uint8_t)((pos >> 8) & 0xFF));
} }

View File

@ -3,18 +3,18 @@
#include "types.h" #include "types.h"
// https://wiki.osdev.org/Text_UI // https://wiki.osdev.org/Text_UI
#define BLACK 0x00 #define BLACK 0x00
#define BLUE 0x01 #define BLUE 0x01
#define GREEN 0x02 #define GREEN 0x02
#define CYAN 0x03 #define CYAN 0x03
#define RED 0x04 #define RED 0x04
#define MAGENTA 0x05 #define MAGENTA 0x05
#define BROWN 0x06 #define BROWN 0x06
#define GREY 0x07 #define GREY 0x07
#define WHITE 0x0F #define WHITE 0x0F
#define VGA_ADDR 0xB8000 #define VGA_ADDR 0xB8000
#define VGA_WIDTH 80 #define VGA_WIDTH 80
#define VGA_HEIGHT 25 #define VGA_HEIGHT 25
#ifndef pr_fmt #ifndef pr_fmt
@ -32,4 +32,3 @@ void vgaScrollUp(void);
void cursorEnable(uint8_t cursor_start, uint8_t cursor_end); void cursorEnable(uint8_t cursor_start, uint8_t cursor_end);
void cursorDisable(void); void cursorDisable(void);
void cursorMove(int x, int y); void cursorMove(int x, int y);

View File

@ -11,135 +11,131 @@
void testPhymem(void) void testPhymem(void)
{ {
printf("Testing memory PHY\n"); printf("Testing memory PHY\n");
struct mem_desc *allocated_page_list; struct mem_desc *allocated_page_list;
struct mem_desc struct mem_desc
*page; // Cast in mem_desc to use it. In fact it's the addr of 4K free memory *page; // Cast in mem_desc to use it. In fact it's the addr of 4K free memory
list_init(allocated_page_list); list_init(allocated_page_list);
int allocCount = 0; int allocCount = 0;
int freeCount = 0; int freeCount = 0;
while ((page = (struct mem_desc *)allocPhyPage()) != NULL) { while ((page = (struct mem_desc *)allocPhyPage()) != NULL) {
page->phy_addr = allocCount; page->phy_addr = allocCount;
allocCount++; allocCount++;
list_add_tail(allocated_page_list, page); list_add_tail(allocated_page_list, page);
} }
printf("%d pages allocated\n", allocCount); printf("%d pages allocated\n", allocCount);
while ((page = list_pop_head(allocated_page_list)) != NULL) { while ((page = list_pop_head(allocated_page_list)) != NULL) {
assertmsg(page->phy_addr == (ulong)freeCount, "page %d modified", page); assertmsg(page->phy_addr == (ulong)freeCount, "page %d modified", page);
assertmsg(unrefPhyPage((ulong)page) >= 0, "Failed to free page %d\n", assertmsg(unrefPhyPage((ulong)page) >= 0, "Failed to free page %d\n", (ulong)page);
(ulong)page); freeCount++;
freeCount++; }
} printf("%d pages freed\n", freeCount);
printf("%d pages freed\n", freeCount);
assertmsg((page = (struct mem_desc *)allocPhyPage()) != NULL, assertmsg((page = (struct mem_desc *)allocPhyPage()) != NULL, "Cannot allocate memory\n");
"Cannot allocate memory\n"); unrefPhyPage((ulong)page);
unrefPhyPage((ulong)page);
} }
static void *testAllocNSet(size_t size) static void *testAllocNSet(size_t size)
{ {
void *allocated = malloc(size); void *allocated = malloc(size);
assert(allocated); assert(allocated);
memset(allocated, size, size); memset(allocated, size, size);
return allocated; return allocated;
} }
static void testAlloc(void) static void testAlloc(void)
{ {
for (uint i = 0; i < PAGE_SIZE / (sizeof(struct slabEntry)); i++) { for (uint i = 0; i < PAGE_SIZE / (sizeof(struct slabEntry)); i++) {
malloc(sizeof(struct slabEntry)); malloc(sizeof(struct slabEntry));
} }
for (uint i = 0; i < PAGE_SIZE / (sizeof(struct slabDesc)); i++) { for (uint i = 0; i < PAGE_SIZE / (sizeof(struct slabDesc)); i++) {
malloc(sizeof(struct slabDesc)); malloc(sizeof(struct slabDesc));
} }
assert(malloc(1)); assert(malloc(1));
assert(malloc(2)); assert(malloc(2));
assert(malloc(3)); assert(malloc(3));
assert(malloc(4)); assert(malloc(4));
void *malloc1 = malloc(sizeof(void *)); void *malloc1 = malloc(sizeof(void *));
void *malloc2 = malloc(sizeof(void *)); void *malloc2 = malloc(sizeof(void *));
assert((char *)malloc2 == ((char *)malloc1 + sizeof(void *))); assert((char *)malloc2 == ((char *)malloc1 + sizeof(void *)));
free(malloc2); free(malloc2);
void *malloc3 = malloc(sizeof(void *)); void *malloc3 = malloc(sizeof(void *));
assertmsg((char *)malloc2 == (char *)malloc3, " %d %d\n", malloc2, malloc3); assertmsg((char *)malloc2 == (char *)malloc3, " %d %d\n", malloc2, malloc3);
void *alloc1 = testAllocNSet(1024); void *alloc1 = testAllocNSet(1024);
void *alloc2 = testAllocNSet(1024); void *alloc2 = testAllocNSet(1024);
void *alloc3 = testAllocNSet(1024); void *alloc3 = testAllocNSet(1024);
void *alloc4 = testAllocNSet(1024); void *alloc4 = testAllocNSet(1024);
void *alloc5 = testAllocNSet(1024); void *alloc5 = testAllocNSet(1024);
void *alloc6 = testAllocNSet(1024); void *alloc6 = testAllocNSet(1024);
void *alloc7 = testAllocNSet(4096); void *alloc7 = testAllocNSet(4096);
free(alloc1); free(alloc1);
free(alloc2); free(alloc2);
free(alloc3); free(alloc3);
free(alloc4); free(alloc4);
free(alloc5); free(alloc5);
free(alloc6); free(alloc6);
free(alloc7); free(alloc7);
void *alloc11 = testAllocNSet(1024); void *alloc11 = testAllocNSet(1024);
void *alloc12 = testAllocNSet(1024); void *alloc12 = testAllocNSet(1024);
void *alloc13 = testAllocNSet(1024); void *alloc13 = testAllocNSet(1024);
void *alloc14 = testAllocNSet(1024); void *alloc14 = testAllocNSet(1024);
void *alloc15 = testAllocNSet(1024); void *alloc15 = testAllocNSet(1024);
void *alloc16 = testAllocNSet(1024); void *alloc16 = testAllocNSet(1024);
free(alloc11); free(alloc11);
free(alloc12); free(alloc12);
free(alloc13); free(alloc13);
free(alloc14); free(alloc14);
free(alloc15); free(alloc15);
free(alloc16); free(alloc16);
} }
static void testPaging(void) static void testPaging(void)
{ {
printf("Testing paging\n"); printf("Testing paging\n");
struct mem_desc *allocated_page_list; struct mem_desc *allocated_page_list;
struct mem_desc struct mem_desc
*page; // Cast in mem_desc to use it. In fact it's the addr of 4K free memory *page; // Cast in mem_desc to use it. In fact it's the addr of 4K free memory
list_init(allocated_page_list); list_init(allocated_page_list);
int allocCount = 0; int allocCount = 0;
int freeCount = 0; int freeCount = 0;
while ((page = (struct mem_desc *)allocPhyPage()) != NULL) { while ((page = (struct mem_desc *)allocPhyPage()) != NULL) {
assertmsg(pageMap((vaddr_t)page, (paddr_t)page, PAGING_MEM_WRITE) == 0, assertmsg(pageMap((vaddr_t)page, (paddr_t)page, PAGING_MEM_WRITE) == 0,
"Fail to map page %d\n", allocCount); "Fail to map page %d\n", allocCount);
memset(page, allocCount, PAGE_SIZE); memset(page, allocCount, PAGE_SIZE);
allocCount++; allocCount++;
list_add_tail(allocated_page_list, page); list_add_tail(allocated_page_list, page);
} }
printf("%d pages allocated\n", allocCount); printf("%d pages allocated\n", allocCount);
while ((page = list_pop_head(allocated_page_list)) != NULL) { while ((page = list_pop_head(allocated_page_list)) != NULL) {
assertmsg((char)page->phy_addr == (char)freeCount, assertmsg((char)page->phy_addr == (char)freeCount, "page modified %d but is %d\n",
"page modified %d but is %d\n", freeCount, page->phy_addr); freeCount, page->phy_addr);
assertmsg(unrefPhyPage((ulong)page) >= 0, "Failed to free page %d\n", assertmsg(unrefPhyPage((ulong)page) >= 0, "Failed to free page %d\n", (ulong)page);
(ulong)page); pageUnmap((vaddr_t)page);
pageUnmap((vaddr_t)page); freeCount++;
freeCount++; }
} printf("%d pages freed\n", freeCount);
printf("%d pages freed\n", freeCount);
assertmsg((page = (struct mem_desc *)allocPhyPage()) != NULL, assertmsg((page = (struct mem_desc *)allocPhyPage()) != NULL, "Cannot allocate memory\n");
"Cannot allocate memory\n"); unrefPhyPage((ulong)page);
unrefPhyPage((ulong)page);
} }
static void test_backtrace_2(int a, int b) static void test_backtrace_2(int a, int b)
{ {
printStackTrace(a + b); printStackTrace(a + b);
} }
static void test_backtrace_1(int a) static void test_backtrace_1(int a)
{ {
test_backtrace_2(a, 3); test_backtrace_2(a, 3);
} }
void test_backtrace() void test_backtrace()
{ {
test_backtrace_1(2); test_backtrace_1(2);
} }
/* ====================================================================== /* ======================================================================
@ -155,14 +151,15 @@ struct cpu_state *ctxt_hello2;
struct cpu_state *ctxt_main; struct cpu_state *ctxt_main;
vaddr_t hello1_stack, hello2_stack; vaddr_t hello1_stack, hello2_stack;
static void reclaim_stack(void * stack_vaddr) static void reclaim_stack(void *stack_vaddr)
{ {
free(stack_vaddr); free(stack_vaddr);
} }
static void exit_hello12(void * stack_vaddr) static void exit_hello12(void *stack_vaddr)
{ {
cpu_context_exit_to(ctxt_main, (cpu_kstate_function_arg1_t *)reclaim_stack, (vaddr_t)stack_vaddr); cpu_context_exit_to(ctxt_main, (cpu_kstate_function_arg1_t *)reclaim_stack,
(vaddr_t)stack_vaddr);
} }
static void hello1(void *strIn) static void hello1(void *strIn)
@ -224,7 +221,7 @@ static void kthread1(void *strIn)
printf("\nkth1: %s\n", (char *)strIn); printf("\nkth1: %s\n", (char *)strIn);
for (; *str != '\n'; str++) { for (; *str != '\n'; str++) {
printf("kth1_: %c\n", *str); printf("kth1_: %c\n", *str);
kthreadYield(); kthreadYield();
} }
} }
@ -234,28 +231,28 @@ static void kthread2(void *strIn)
printf("\nkth2: %s\n", (char *)strIn); printf("\nkth2: %s\n", (char *)strIn);
for (; *str != '\n'; str++) { for (; *str != '\n'; str++) {
printf("kth2_: %c\n", *str); printf("kth2_: %c\n", *str);
kthreadYield(); kthreadYield();
} }
} }
void testKthread() void testKthread()
{ {
kthreadCreate("Test1", (cpu_kstate_function_arg1_t *)kthread1, (void *)"Hlowrd\n"); kthreadCreate("Test1", (cpu_kstate_function_arg1_t *)kthread1, (void *)"Hlowrd\n");
kthreadCreate("Test2", (cpu_kstate_function_arg1_t *)kthread2, (void *)"el ol\n"); kthreadCreate("Test2", (cpu_kstate_function_arg1_t *)kthread2, (void *)"el ol\n");
} }
void run_test(void) void run_test(void)
{ {
testPaging(); testPaging();
printf("Testing Serial\n"); printf("Testing Serial\n");
serialPutc('h'); serialPutc('h');
serialPutc('e'); serialPutc('e');
serialPutc('l'); serialPutc('l');
serialPutc('l'); serialPutc('l');
serialPutc('o'); serialPutc('o');
testAlloc(); testAlloc();
printf("Testing backtrace\n"); printf("Testing backtrace\n");
test_backtrace(); test_backtrace();
testCoroutine(); testCoroutine();
testKthread(); testKthread();
} }