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

View File

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

View File

@ -24,34 +24,34 @@
* irq_wrappers.S/exception_wrappers.S !!! Hence the constraint above.
*/
struct cpu_state {
/* (Lower addresses) */
/* (Lower addresses) */
/* These are Matos/SOS convention */
uint16_t gs;
uint16_t fs;
uint16_t es;
uint16_t ds;
uint16_t cpl0_ss; /* This is ALWAYS the Stack Segment of the
Kernel context (CPL0) of the interrupted
thread, even for a user thread */
uint16_t alignment_padding; /* unused */
uint32_t eax;
uint32_t ecx;
uint32_t edx;
uint32_t ebx;
uint32_t ebp;
uint32_t esp;
uint32_t esi;
uint32_t edi;
/* These are Matos/SOS convention */
uint16_t gs;
uint16_t fs;
uint16_t es;
uint16_t ds;
uint16_t cpl0_ss; /* This is ALWAYS the Stack Segment of the
Kernel context (CPL0) of the interrupted
thread, even for a user thread */
uint16_t alignment_padding; /* unused */
uint32_t eax;
uint32_t ecx;
uint32_t edx;
uint32_t ebx;
uint32_t ebp;
uint32_t esp;
uint32_t esi;
uint32_t edi;
/* MUST NEVER CHANGE (dependent on the IA32 iret instruction) */
uint32_t error_code;
vaddr_t eip;
uint32_t cs; /* 32bits according to the specs ! However, the CS
register is really 16bits long */
uint32_t eflags;
/* MUST NEVER CHANGE (dependent on the IA32 iret instruction) */
uint32_t error_code;
vaddr_t eip;
uint32_t cs; /* 32bits according to the specs ! However, the CS
register is really 16bits long */
uint32_t eflags;
/* (Higher addresses) */
/* (Higher addresses) */
} __attribute__((packed));
/**
@ -73,7 +73,7 @@ struct cpu_state {
* Structure of an interrupted Kernel thread's context
*/
struct cpu_kstate {
struct cpu_state regs;
struct cpu_state regs;
} __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,
cpu_kstate_function_arg1_t *exit_func, void *exit_arg)
{
start_func(start_arg);
exit_func(exit_arg);
start_func(start_arg);
exit_func(exit_arg);
assert(!"The exit function of the thread should NOT return !");
for (;;)
;
assert(!"The exit function of the thread should NOT return !");
for (;;)
;
}
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,
cpu_kstate_function_arg1_t *exit_func, vaddr_t exit_arg)
{
/* We are initializing a Kernel thread's context */
struct cpu_kstate *kctxt;
/* We are initializing a Kernel thread's context */
struct cpu_kstate *kctxt;
/* This is a critical internal function, so that it is assumed that
the caller knows what he does: we legitimally assume that values
for ctxt, start_func, stack_* and exit_func are allways VALID ! */
/* This is a critical internal function, so that it is assumed that
the caller knows what he does: we legitimally assume that values
for ctxt, start_func, stack_* and exit_func are allways VALID ! */
/* Setup the stack.
*
* On x86, the stack goes downward. Each frame is configured this
* way (higher addresses first):
*
* - (optional unused space. As of gcc 3.3, this space is 24 bytes)
* - arg n
* - arg n-1
* - ...
* - arg 1
* - return instruction address: The address the function returns to
* once finished
* - local variables
*
* The remaining of the code should be read from the end upward to
* understand how the processor will handle it.
*/
/* Setup the stack.
*
* On x86, the stack goes downward. Each frame is configured this
* way (higher addresses first):
*
* - (optional unused space. As of gcc 3.3, this space is 24 bytes)
* - arg n
* - arg n-1
* - ...
* - arg 1
* - return instruction address: The address the function returns to
* once finished
* - local variables
*
* The remaining of the code should be read from the end upward to
* understand how the processor will handle it.
*/
vaddr_t tmp_vaddr = stack_bottom + stack_size;
uint32_t *stack = (uint32_t *)tmp_vaddr;
vaddr_t tmp_vaddr = stack_bottom + stack_size;
uint32_t *stack = (uint32_t *)tmp_vaddr;
/* If needed, poison the stack */
/* If needed, poison the stack */
#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)
cpu_state_prepare_detect_kernel_stack_overflow(stack_bottom, stack_size);
cpu_state_prepare_detect_kernel_stack_overflow(stack_bottom, stack_size);
#endif
/* Simulate a call to the core_routine() function: prepare its
arguments */
*(--stack) = exit_arg;
*(--stack) = (uint32_t)exit_func;
*(--stack) = start_arg;
*(--stack) = (uint32_t)start_func;
*(--stack) = 0; /* Return address of core_routine => force page fault */
/* Simulate a call to the core_routine() function: prepare its
arguments */
*(--stack) = exit_arg;
*(--stack) = (uint32_t)exit_func;
*(--stack) = start_arg;
*(--stack) = (uint32_t)start_func;
*(--stack) = 0; /* Return address of core_routine => force page fault */
/*
* Setup the initial context structure, so that the CPU will execute
* the function core_routine() once this new context has been
* restored on CPU
*/
/*
* Setup the initial context structure, so that the CPU will execute
* the function core_routine() once this new context has been
* restored on CPU
*/
/* Compute the base address of the structure, which must be located
below the previous elements */
tmp_vaddr = ((vaddr_t)stack) - sizeof(struct cpu_kstate);
kctxt = (struct cpu_kstate *)tmp_vaddr;
/* Compute the base address of the structure, which must be located
below the previous elements */
tmp_vaddr = ((vaddr_t)stack) - sizeof(struct cpu_kstate);
kctxt = (struct cpu_kstate *)tmp_vaddr;
/* Initialize the CPU context structure */
memset(kctxt, 0x0, sizeof(struct cpu_kstate));
/* Initialize the CPU context structure */
memset(kctxt, 0x0, sizeof(struct cpu_kstate));
/* Tell the CPU context structure that the first instruction to
execute will be that of the core_routine() function */
kctxt->regs.eip = (uint32_t)core_routine;
/* Tell the CPU context structure that the first instruction to
execute will be that of the core_routine() function */
kctxt->regs.eip = (uint32_t)core_routine;
/* Setup the segment registers */
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.es = BUILD_SEGMENT_REG_VALUE(0, FALSE, SEG_KDATA); /* Data */
kctxt->regs.cpl0_ss = BUILD_SEGMENT_REG_VALUE(0, FALSE, SEG_KDATA); /* Stack */
/* fs and gs unused for the moment. */
/* Setup the segment registers */
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.es = BUILD_SEGMENT_REG_VALUE(0, FALSE, SEG_KDATA); /* Data */
kctxt->regs.cpl0_ss = BUILD_SEGMENT_REG_VALUE(0, FALSE, SEG_KDATA); /* Stack */
/* fs and gs unused for the moment. */
/* The newly created context is initially interruptible */
kctxt->regs.eflags = (1 << 9); /* set IF bit */
/* The newly created context is initially interruptible */
kctxt->regs.eflags = (1 << 9); /* set IF bit */
/* Finally, update the generic kernel/user thread context */
*ctxt = (struct cpu_state *)kctxt;
/* Finally, update the generic kernel/user thread context */
*ctxt = (struct cpu_state *)kctxt;
return 0;
return 0;
}
#if defined(CPU_STATE_DETECT_KERNEL_STACK_OVERFLOW)
void cpu_state_prepare_detect_kernel_stack_overflow(const struct cpu_state *ctxt,
vaddr_t stack_bottom, size_t stack_size)
{
(void)ctxt;
size_t poison_size = CPU_STATE_DETECT_KERNEL_STACK_OVERFLOW;
if (poison_size > stack_size)
poison_size = stack_size;
(void)ctxt;
size_t poison_size = CPU_STATE_DETECT_KERNEL_STACK_OVERFLOW;
if (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,
size_t stack_size)
{
unsigned char *c;
size_t i;
unsigned char *c;
size_t i;
/* On Matos/SOS, "ctxt" corresponds to the address of the esp register of
the saved context in Kernel mode (always, even for the interrupted
context of a user thread). Here we make sure that this stack
pointer is within the allowed stack area */
assert(((vaddr_t)ctxt) >= stack_bottom);
assert(((vaddr_t)ctxt) + sizeof(struct cpu_kstate) <= stack_bottom + stack_size);
/* On Matos/SOS, "ctxt" corresponds to the address of the esp register of
the saved context in Kernel mode (always, even for the interrupted
context of a user thread). Here we make sure that this stack
pointer is within the allowed stack area */
assert(((vaddr_t)ctxt) >= stack_bottom);
assert(((vaddr_t)ctxt) + sizeof(struct cpu_kstate) <= stack_bottom + stack_size);
/* Check that the bottom of the stack has not been altered */
for (c = (unsigned char *)stack_bottom, i = 0;
(i < CPU_STATE_DETECT_KERNEL_STACK_OVERFLOW) && (i < stack_size); c++, i++) {
assert(CPU_STATE_STACK_POISON == *c);
}
/* Check that the bottom of the stack has not been altered */
for (c = (unsigned char *)stack_bottom, i = 0;
(i < CPU_STATE_DETECT_KERNEL_STACK_OVERFLOW) && (i < stack_size); c++, i++) {
assert(CPU_STATE_STACK_POISON == *c);
}
}
#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)
{
assert(NULL != ctxt);
assert(NULL != ctxt);
/* This is the PC of the interrupted context (ie kernel or user
context). */
return ctxt->eip;
/* This is the PC of the interrupted context (ie kernel or user
context). */
return ctxt->eip;
}
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
the saved context in Kernel mode (always, even for the interrupted
context of a user thread). */
return (vaddr_t)ctxt;
/* On Matos/SOS, "ctxt" corresponds to the address of the esp register of
the saved context in Kernel mode (always, even for the interrupted
context of a user thread). */
return (vaddr_t)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,
(unsigned)ctxt, (unsigned)ctxt->eflags, (unsigned)GET_CPU_CS_REGISTER_VALUE(ctxt->cs),
(unsigned)ctxt->ds, (unsigned)ctxt->cpl0_ss, (unsigned)ctxt->error_code);
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->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
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
USA.
USA.
*/
#pragma once
@ -25,10 +25,9 @@
* be some kind of architecture-independent.
*/
#include "errno.h"
#include "stdarg.h"
#include "types.h"
#include "errno.h"
/**
* Opaque structure storing the CPU context of an inactive kernel or
@ -41,13 +40,11 @@
*/
struct cpu_state;
/**
* The type of the functions passed as arguments to the Kernel thread
* 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
@ -83,14 +80,9 @@ typedef void (cpu_kstate_function_arg1_t(void * arg1));
*
* @note the newly created context is INTERRUPTIBLE by default !
*/
int cpu_kstate_init(struct cpu_state **kctxt,
cpu_kstate_function_arg1_t *start_func,
vaddr_t start_arg,
vaddr_t stack_bottom,
size_t stack_size,
cpu_kstate_function_arg1_t *exit_func,
vaddr_t exit_arg);
int cpu_kstate_init(struct cpu_state **kctxt, cpu_kstate_function_arg1_t *start_func,
vaddr_t start_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
@ -103,9 +95,7 @@ int cpu_kstate_init(struct cpu_state **kctxt,
* @param to_ctxt The CPU will resume its execution with the struct
* cpu_state located at this address. Must NOT be NULL.
*/
void cpu_context_switch(struct cpu_state **from_ctxt,
struct cpu_state *to_ctxt);
void cpu_context_switch(struct cpu_state **from_ctxt, struct cpu_state *to_ctxt);
/*
* 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
* context to switch_to_ctxt.
*/
void
cpu_context_exit_to(struct cpu_state *switch_to_ctxt,
cpu_kstate_function_arg1_t *reclaiming_func,
uint32_t reclaiming_arg) __attribute__((noreturn));
void cpu_context_exit_to(struct cpu_state *switch_to_ctxt,
cpu_kstate_function_arg1_t *reclaiming_func, uint32_t reclaiming_arg)
__attribute__((noreturn));
/* =======================================================================
* Public Accessor functions
*/
/**
* Return Program Counter stored in the saved kernel/user context
*/
vaddr_t cpu_context_get_PC(const struct cpu_state *ctxt);
/**
* Return Stack Pointer stored in the saved kernel/user context
*/
vaddr_t cpu_context_get_SP(const struct cpu_state *ctxt);
/**
* Dump the contents of the CPU context (bochs + x86_videomem)
*/
void cpu_context_dump(const struct cpu_state *ctxt);
/* =======================================================================
* Public Accessor functions TO BE USED ONLY BY Exception handlers
*/
/**
* Return the argument passed by the CPU upon exception, as stored in the
* saved context
*/
uint32_t cpu_context_get_EX_info(const struct cpu_state *ctxt);
/**
* Return the faulting address of the exception
*/
vaddr_t
cpu_context_get_EX_faulting_vaddr(const struct cpu_state *ctxt);
vaddr_t cpu_context_get_EX_faulting_vaddr(const struct cpu_state *ctxt);
/* =======================================================================
* 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
* 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 */
#if defined(CPU_STATE_DETECT_KERNEL_STACK_OVERFLOW)
void
cpu_state_prepare_detect_kernel_stack_overflow(const struct cpu_state *ctxt,
vaddr_t kernel_stack_bottom,
size_t kernel_stack_size);
void cpu_state_prepare_detect_kernel_stack_overflow(const struct cpu_state *ctxt,
vaddr_t kernel_stack_bottom,
size_t kernel_stack_size);
void cpu_state_detect_kernel_stack_overflow(const struct cpu_state *ctxt,
vaddr_t kernel_stack_bottom,
size_t kernel_stack_size);
vaddr_t kernel_stack_bottom,
size_t kernel_stack_size);
#else
# define cpu_state_prepare_detect_kernel_stack_overflow(ctxt,stkbottom,stksize) \
({ /* nop */ })
# define cpu_state_detect_kernel_stack_overflow(ctxt,stkbottom,stksize) \
({ /* nop */ })
#define cpu_state_prepare_detect_kernel_stack_overflow(ctxt, stkbottom, stksize) ({/* nop \
*/})
#define cpu_state_detect_kernel_stack_overflow(ctxt, stkbottom, stksize) ({/* nop */})
#endif

View File

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

View File

@ -41,6 +41,5 @@
#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);

View File

@ -6,16 +6,16 @@
// Need GCC > 6
#define DEFINE_INTERRUPT(int_nb) \
__attribute__((interrupt)) void print_handler_##int_nb(struct interrupt_frame *frame, \
ulong error_code) \
{ \
int intNbInt = int_nb; \
printStringDetails("EXCEPTION ", RED, BLACK, 0, VGA_HEIGHT - 1); \
printIntDetails(intNbInt, RED, BLACK, 11, 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); \
asm("hlt"); \
}
__attribute__((interrupt)) void print_handler_##int_nb(struct interrupt_frame *frame, \
ulong error_code) \
{ \
int intNbInt = int_nb; \
printStringDetails("EXCEPTION ", RED, BLACK, 0, VGA_HEIGHT - 1); \
printIntDetails(intNbInt, RED, BLACK, 11, 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); \
asm("hlt"); \
}
DEFINE_INTERRUPT(EXCEPTION_DOUBLE_FAULT)
DEFINE_INTERRUPT(EXCEPTION_DIVIDE_ZERO)
@ -56,14 +56,14 @@ DEFINE_INTERRUPT(EXCEPTION_RESERVED_11)
__attribute__((interrupt)) void pagefault_handler(struct interrupt_frame *frame,
ulong error_code)
{
// A page fault has occurred.
// The faulting address is stored in the CR2 register.
uint32_t faulting_address;
asm volatile("mov %%cr2, %0" : "=r"(faulting_address));
// A page fault has occurred.
// The faulting address is stored in the CR2 register.
uint32_t faulting_address;
asm volatile("mov %%cr2, %0" : "=r"(faulting_address));
printStringDetails("PAGE FAULT", RED, BLACK, 0, VGA_HEIGHT - 1);
printIntDetails(error_code, RED, BLACK, 11, VGA_HEIGHT - 1);
(void)faulting_address;
(void)frame;
(void)error_code;
printStringDetails("PAGE FAULT", RED, BLACK, 0, VGA_HEIGHT - 1);
printIntDetails(error_code, RED, BLACK, 11, VGA_HEIGHT - 1);
(void)faulting_address;
(void)frame;
(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
* addresses.
*/
#define BUILD_GDTE(descr_privilege_level, is_code) \
((struct x86_segment_descriptor){ \
.limit_15_0 = 0xffff, \
.base_paged_addr_15_0 = 0, \
.base_paged_addr_23_16 = 0, \
.segment_type = \
((is_code) ? 0xb : 0x3), /* With descriptor_type (below) = 1 (code/data), \
* see Figure 3-1 of section 3.4.3.1 in Intel \
* x86 vol 3: \
* - Code (bit 3 = 1): \
* bit 0: 1=Accessed \
* bit 1: 1=Readable \
* bit 2: 0=Non-Conforming \
* - Data (bit 3 = 0): \
* bit 0: 1=Accessed \
* bit 1: 1=Writable \
* bit 2: 0=Expand up (stack-related) \
* For Conforming/non conforming segments, see \
* Intel x86 Vol 3 section 4.8.1.1 \
*/ \
.descriptor_type = 1, /* 1=Code/Data */ \
.dpl = ((descr_privilege_level)&0x3), \
.present = 1, \
.limit_19_16 = 0xf, \
.custom = 0, \
.op_size = 1, /* 32 bits instr/data */ \
.granularity = 1 /* limit is in 4kB Pages */ \
#define BUILD_GDTE(descr_privilege_level, is_code) \
((struct x86_segment_descriptor){ \
.limit_15_0 = 0xffff, \
.base_paged_addr_15_0 = 0, \
.base_paged_addr_23_16 = 0, \
.segment_type = ((is_code) ? 0xb : 0x3), /* With descriptor_type (below) = 1 \
* (code/data), see Figure 3-1 of \
* section 3.4.3.1 in Intel x86 vol 3: \
* - Code (bit 3 = 1): \
* bit 0: 1=Accessed \
* bit 1: 1=Readable \
* bit 2: 0=Non-Conforming \
* - Data (bit 3 = 0): \
* bit 0: 1=Accessed \
* bit 1: 1=Writable \
* bit 2: 0=Expand up (stack-related) \
* For Conforming/non conforming segments, \
* see Intel x86 Vol 3 section 4.8.1.1 \
*/ \
.descriptor_type = 1, /* 1=Code/Data */ \
.dpl = ((descr_privilege_level)&0x3), \
.present = 1, \
.limit_19_16 = 0xf, \
.custom = 0, \
.op_size = 1, /* 32 bits instr/data */ \
.granularity = 1 /* limit is in 4kB Pages */ \
})
/** The actual GDT */

View File

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

View File

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

View File

@ -1,20 +1,19 @@
#pragma once
#include "stdarg.h"
// c.f. intel software-developer-vol-1 6.4.1
struct interrupt_frame {
uint32_t eip;
uint32_t cs;
uint32_t eflags;
uint32_t esp;
uint32_t ss;
uint32_t eip;
uint32_t cs;
uint32_t eflags;
uint32_t esp;
uint32_t ss;
};
// Exception
// Exception
#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

View File

@ -4,18 +4,17 @@
// NIH http://wiki.osdev.org/Inline_Assembly/Examples#I.2FO_access
static inline void outb(uint16_t port, uint8_t val)
{
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).
* Wider immediate constants would be truncated at assemble-time (e.g. "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 */
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). Wider immediate constants would be truncated at assemble-time (e.g.
* "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 */
}
static inline uint8_t inb(uint16_t port)
{
uint8_t ret;
asm volatile ( "inb %1, %0"
: "=a"(ret)
: "Nd"(port) );
asm volatile("inb %1, %0" : "=a"(ret) : "Nd"(port));
return ret;
}

View File

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

View File

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

View File

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

View File

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

View File

@ -10,96 +10,96 @@ static struct kthread *currentThread;
void kthreadExit()
{
uint32_t flags;
disable_IRQs(flags);
struct kthread *current = currentThread;
struct kthread *next = kthreadSelectNext();
if (next == current)
assert("cannot exit thread");
currentThread = next;
cpu_context_exit_to(next->cpuState, (cpu_kstate_function_arg1_t *)kthreadDelete,
(uint32_t)current);
restore_IRQs(flags);
return;
uint32_t flags;
disable_IRQs(flags);
struct kthread *current = currentThread;
struct kthread *next = kthreadSelectNext();
if (next == current)
assert("cannot exit thread");
currentThread = next;
cpu_context_exit_to(next->cpuState, (cpu_kstate_function_arg1_t *)kthreadDelete,
(uint32_t)current);
restore_IRQs(flags);
return;
}
int kthreadSetup(vaddr_t mainStack, size_t mainStackSize)
{
struct kthread *current = (struct kthread *)malloc(sizeof(struct kthread));
strzcpy(current->name, "[KINIT]", KTHREAD_NAME_MAX_LENGTH);
current->stackAddr = mainStack;
current->stackSize = mainStackSize;
struct kthread *current = (struct kthread *)malloc(sizeof(struct kthread));
strzcpy(current->name, "[KINIT]", KTHREAD_NAME_MAX_LENGTH);
current->stackAddr = mainStack;
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 *thread = (struct kthread *)malloc(sizeof(struct kthread));
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);
struct kthread *thread = (struct kthread *)malloc(sizeof(struct kthread));
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;
}
void kthreadDelete(struct kthread *thread)
{
list_delete(currentThread, thread);
list_delete(currentThread, thread);
free((void *)thread->stackAddr);
free((void *)thread);
free((void *)thread->stackAddr);
free((void *)thread);
}
struct kthread *kthreadSelectNext()
{
struct kthread *nextThread = currentThread->next;
return nextThread;
struct kthread *nextThread = currentThread->next;
return nextThread;
}
struct cpu_state *switchKthread(struct cpu_state *prevCpu)
{
uint32_t flags;
disable_IRQs(flags);
currentThread->cpuState = prevCpu;
struct kthread *nextThread = kthreadSelectNext();
printStringDetails(nextThread->name, RED, BLACK, 40, VGA_HEIGHT - 1);
currentThread = nextThread;
restore_IRQs(flags);
return nextThread->cpuState;
uint32_t flags;
disable_IRQs(flags);
currentThread->cpuState = prevCpu;
struct kthread *nextThread = kthreadSelectNext();
printStringDetails(nextThread->name, RED, BLACK, 40, VGA_HEIGHT - 1);
currentThread = nextThread;
restore_IRQs(flags);
return nextThread->cpuState;
}
int kthreadYield()
{
uint32_t flags;
disable_IRQs(flags);
struct kthread *next = kthreadSelectNext();
struct kthread *current = currentThread;
currentThread = next;
cpu_context_switch(&current->cpuState, next->cpuState);
restore_IRQs(flags);
return 0;
uint32_t flags;
disable_IRQs(flags);
struct kthread *next = kthreadSelectNext();
struct kthread *current = currentThread;
currentThread = next;
cpu_context_switch(&current->cpuState, next->cpuState);
restore_IRQs(flags);
return 0;
}

View File

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

View File

@ -1,15 +1,15 @@
/* Copyright (C) 2001 David Decotigny
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
@ -25,170 +25,165 @@
* macros
*/
/* *_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,
prev_global and next_global */
#define list_init_named(list,prev,next) \
((list) = NULL)
#define list_init_named(list, prev, next) ((list) = NULL)
#define list_singleton_named(list,item,prev,next) ({ \
(item)->next = (item)->prev = (item); \
(list) = (item); \
})
#define list_singleton_named(list, item, prev, next) \
({ \
(item)->next = (item)->prev = (item); \
(list) = (item); \
})
#define list_is_empty_named(list,prev,next) \
((list) == NULL)
#define list_is_empty_named(list, prev, next) ((list) == NULL)
#define list_is_singleton_named(list,prev,next) \
( ((list) != NULL) && ((list)->prev == (list)->next) && ((list) == (list)->next) )
#define list_is_singleton_named(list, prev, next) \
(((list) != NULL) && ((list)->prev == (list)->next) && ((list) == (list)->next))
#define list_get_head_named(list,prev,next) \
(list)
#define list_get_head_named(list, prev, next) (list)
#define list_get_tail_named(list,prev,next) \
((list)?((list)->prev):NULL)
#define list_get_tail_named(list, prev, next) ((list) ? ((list)->prev) : NULL)
/* Internal macro : insert before the head == insert at tail */
#define __list_insert_atleft_named(before_this,item,prev,next) ({ \
(before_this)->prev->next = (item); \
(item)->prev = (before_this)->prev; \
(before_this)->prev = (item); \
(item)->next = (before_this); \
})
#define __list_insert_atleft_named(before_this, item, prev, next) \
({ \
(before_this)->prev->next = (item); \
(item)->prev = (before_this)->prev; \
(before_this)->prev = (item); \
(item)->next = (before_this); \
})
/* @note Before_this and item are expected to be valid ! */
#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); \
})
#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); \
})
/** @note After_this and item are expected to be valid ! */
#define list_insert_after_named(list,after_this,item,prev,next) ({ \
(after_this)->next->prev = (item); \
(item)->next = (after_this)->next; \
(after_this)->next = (item); \
(item)->prev = (after_this); \
})
#define list_insert_after_named(list, after_this, item, prev, next) \
({ \
(after_this)->next->prev = (item); \
(item)->next = (after_this)->next; \
(after_this)->next = (item); \
(item)->prev = (after_this); \
})
#define list_add_head_named(list,item,prev,next) ({ \
if (list) \
list_insert_before_named(list,list,item,prev,next); \
else \
list_singleton_named(list,item,prev,next); \
(list) = (item); \
})
#define list_add_head_named(list, item, prev, next) \
({ \
if (list) \
list_insert_before_named(list, list, item, prev, next); \
else \
list_singleton_named(list, item, prev, next); \
(list) = (item); \
})
#define list_add_tail_named(list,item,prev,next) ({ \
if (list) \
__list_insert_atleft_named(list,item,prev,next); \
else \
list_singleton_named(list,item,prev,next); \
})
#define list_add_tail_named(list, item, prev, next) \
({ \
if (list) \
__list_insert_atleft_named(list, item, prev, next); \
else \
list_singleton_named(list, item, prev, next); \
})
/** @note NO check whether item really is in list ! */
#define list_delete_named(list,item,prev,next) ({ \
if ( ((item)->next == (item)) && ((item)->prev == (item)) ) \
(item)->next = (item)->prev = (list) = NULL; \
else { \
(item)->prev->next = (item)->next; \
(item)->next->prev = (item)->prev; \
if ((item) == (list)) (list) = (item)->next; \
(item)->prev = (item)->next = NULL; \
} \
})
#define list_delete_named(list, item, prev, next) \
({ \
if (((item)->next == (item)) && ((item)->prev == (item))) \
(item)->next = (item)->prev = (list) = NULL; \
else { \
(item)->prev->next = (item)->next; \
(item)->next->prev = (item)->prev; \
if ((item) == (list)) \
(list) = (item)->next; \
(item)->prev = (item)->next = NULL; \
} \
})
#define list_pop_head_named(list,prev,next) ({ \
typeof(list) __ret_elt = (list); \
list_delete_named(list,__ret_elt,prev,next); \
__ret_elt; })
#define list_pop_head_named(list, prev, next) \
({ \
typeof(list) __ret_elt = (list); \
list_delete_named(list, __ret_elt, prev, next); \
__ret_elt; \
})
/** Loop statement that iterates through all of its elements, from
head to tail */
#define list_foreach_forward_named(list,iterator,nb_elements,prev,next) \
for (nb_elements=0, (iterator) = (list) ; \
(iterator) && (!nb_elements || ((iterator) != (list))) ; \
nb_elements++, (iterator) = (iterator)->next )
#define list_foreach_forward_named(list, iterator, nb_elements, prev, next) \
for (nb_elements = 0, (iterator) = (list); \
(iterator) && (!nb_elements || ((iterator) != (list))); \
nb_elements++, (iterator) = (iterator)->next)
/** Loop statement that iterates through all of its elements, from
tail back to head */
#define list_foreach_backward_named(list,iterator,nb_elements,prev,next) \
for (nb_elements=0, (iterator) = list_get_tail_named(list,prev,next) ; \
(iterator) && (!nb_elements || \
((iterator) != list_get_tail_named(list,prev,next))) ; \
nb_elements++, (iterator) = (iterator)->prev )
#define list_foreach_backward_named(list, iterator, nb_elements, prev, next) \
for (nb_elements = 0, (iterator) = list_get_tail_named(list, prev, next); \
(iterator) && \
(!nb_elements || ((iterator) != list_get_tail_named(list, prev, next))); \
nb_elements++, (iterator) = (iterator)->prev)
#define list_foreach_named list_foreach_forward_named
/** True when we exitted early from the foreach loop (ie break) */
#define list_foreach_early_break(list,iterator,nb_elements) \
((list) && ( \
((list) != (iterator)) || \
( ((list) == (iterator)) && (nb_elements == 0)) ))
#define list_foreach_early_break(list, iterator, nb_elements) \
((list) && (((list) != (iterator)) || (((list) == (iterator)) && (nb_elements == 0))))
/** Loop statement that also removes the item at each iteration. The
body of the loop is allowed to delete the iterator element from
memory. */
#define list_collapse_named(list,iterator,prev,next) \
for ( ; ({ ((iterator) = (list)) ; \
if (list) list_delete_named(list,iterator,prev,next) ; \
(iterator); }) ; )
#define list_collapse_named(list, iterator, prev, next) \
for (; ({ \
((iterator) = (list)); \
if (list) \
list_delete_named(list, iterator, prev, next); \
(iterator); \
});)
/*
* the same macros : assume that the prev and next fields are really
* named "prev" and "next"
*/
#define list_init(list) \
list_init_named(list,prev,next)
#define list_init(list) list_init_named(list, prev, next)
#define list_singleton(list,item) \
list_singleton_named(list,item,prev,next)
#define list_singleton(list, item) list_singleton_named(list, item, prev, next)
#define list_is_empty(list) \
list_is_empty_named(list,prev,next)
#define list_is_empty(list) list_is_empty_named(list, prev, next)
#define list_is_singleton(list) \
list_is_singleton_named(list,prev,next)
#define list_is_singleton(list) list_is_singleton_named(list, prev, next)
#define list_get_head(list) \
list_get_head_named(list,prev,next) \
#define list_get_head(list) list_get_head_named(list, prev, next)
#define list_get_tail(list) \
list_get_tail_named(list,prev,next) \
#define list_get_tail(list) list_get_tail_named(list, prev, next)
/* @note Before_this and item are expected to be valid ! */
#define list_insert_after(list,after_this,item) \
list_insert_after_named(list,after_this,item,prev,next)
#define list_insert_after(list, after_this, item) \
list_insert_after_named(list, after_this, item, prev, next)
/* @note After_this and item are expected to be valid ! */
#define list_insert_before(list,before_this,item) \
list_insert_before_named(list,before_this,item,prev,next)
#define list_insert_before(list, before_this, item) \
list_insert_before_named(list, before_this, item, prev, next)
#define list_add_head(list,item) \
list_add_head_named(list,item,prev,next)
#define list_add_head(list, item) list_add_head_named(list, item, prev, next)
#define list_add_tail(list,item) \
list_add_tail_named(list,item,prev,next)
#define list_add_tail(list, item) list_add_tail_named(list, item, prev, next)
/* @note NO check whether item really is in list ! */
#define list_delete(list,item) \
list_delete_named(list,item,prev,next)
#define list_delete(list, item) list_delete_named(list, item, prev, next)
#define list_pop_head(list) \
list_pop_head_named(list,prev,next)
#define list_pop_head(list) list_pop_head_named(list, prev, next)
#define list_foreach_forward(list,iterator,nb_elements) \
list_foreach_forward_named(list,iterator,nb_elements,prev,next)
#define list_foreach_forward(list, iterator, nb_elements) \
list_foreach_forward_named(list, iterator, nb_elements, prev, next)
#define list_foreach_backward(list,iterator,nb_elements) \
list_foreach_backward_named(list,iterator,nb_elements,prev,next)
#define list_foreach_backward(list, iterator, nb_elements) \
list_foreach_backward_named(list, iterator, nb_elements, prev, next)
#define list_foreach list_foreach_forward
#define list_collapse(list,iterator) \
list_collapse_named(list,iterator,prev,next)
#define list_collapse(list, iterator) list_collapse_named(list, iterator, prev, next)
#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");
}
void idleThread(void *arg){
void idleThread(void *arg)
{
(void)arg;
int count = 0;
while(1)
while (1)
printIntDetails(count++, GREEN, BLACK, 0, VGA_HEIGHT - 1);
}
// Multiboot information available here :
// 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
@ -83,7 +83,7 @@ void kmain(unsigned long magic, unsigned long addr)
struct multiboot_mmap_entry *mmap = (struct multiboot_mmap_entry *)mbi->mmap_addr;
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,
sizeof(multiboot_memory_map_t));
sizeof(multiboot_memory_map_t));
for (uint i = 0; i < size; i++) {
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),
@ -112,8 +112,8 @@ void kmain(unsigned long magic, unsigned long addr)
printf("Enabling HW interrupts\n");
exceptionSetRoutine(EXCEPTION_DOUBLE_FAULT, ACCESS_INTERRUPT(EXCEPTION_DOUBLE_FAULT));
exceptionSetRoutine(EXCEPTION_DIVIDE_ZERO, ACCESS_INTERRUPT(EXCEPTION_DIVIDE_ZERO));
//Used by the DBG
//exceptionSetRoutine(EXCEPTION_DEBUG, ACCESS_INTERRUPT(EXCEPTION_DEBUG));
// Used by the DBG
// exceptionSetRoutine(EXCEPTION_DEBUG, ACCESS_INTERRUPT(EXCEPTION_DEBUG));
exceptionSetRoutine(EXCEPTION_NMI, ACCESS_INTERRUPT(EXCEPTION_NMI));
exceptionSetRoutine(EXCEPTION_BREAKPOINT, ACCESS_INTERRUPT(EXCEPTION_BREAKPOINT));
exceptionSetRoutine(EXCEPTION_OVERFLOW, ACCESS_INTERRUPT(EXCEPTION_OVERFLOW));

View File

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

View File

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

View File

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

View File

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

View File

@ -26,181 +26,179 @@
static unsigned long mappedPage = 0;
struct pde {
uint32_t present : 1;
uint32_t write : 1; // 0 read - 1 RW
uint32_t user : 1; // 0 supervisor - 1 user
uint32_t write_through : 1; // 0 write-back - 1 write_through
uint32_t cache_disable : 1;
uint32_t access : 1; // have been accessed
uint32_t zero : 1; // Not used
uint32_t size : 1; // 0 for 4Kb 1 for 4Mb
uint32_t ignored : 1;
uint32_t available : 3;
uint32_t pt_addr : 20;
uint32_t present : 1;
uint32_t write : 1; // 0 read - 1 RW
uint32_t user : 1; // 0 supervisor - 1 user
uint32_t write_through : 1; // 0 write-back - 1 write_through
uint32_t cache_disable : 1;
uint32_t access : 1; // have been accessed
uint32_t zero : 1; // Not used
uint32_t size : 1; // 0 for 4Kb 1 for 4Mb
uint32_t ignored : 1;
uint32_t available : 3;
uint32_t pt_addr : 20;
} __attribute__((packed));
struct pte {
uint32_t present : 1;
uint32_t write : 1; // 0 read - 1 RW
uint32_t user : 1; // 0 supervisor - 1 user
uint32_t write_through : 1; // 0 write-back - 1 write_through
uint32_t cache_disable : 1;
uint32_t access : 1; // have been accessed
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.
uint32_t zero : 1; // if PAT is supported, shall indicate the memory type. Otherwise,
// it must be 0.
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
// must be set to enable this feature.
uint32_t available : 3;
uint32_t paddr : 20;
uint32_t present : 1;
uint32_t write : 1; // 0 read - 1 RW
uint32_t user : 1; // 0 supervisor - 1 user
uint32_t write_through : 1; // 0 write-back - 1 write_through
uint32_t cache_disable : 1;
uint32_t access : 1; // have been accessed
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.
uint32_t zero : 1; // if PAT is supported, shall indicate the memory type. Otherwise,
// it must be 0.
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
// must be set to enable this feature.
uint32_t available : 3;
uint32_t paddr : 20;
} __attribute__((packed));
struct pdbr {
uint32_t zero1 : 3; // reserved
uint32_t write_through : 1; // 0 write-back - 1 write-through
uint32_t cache_disabled : 1; // 1=cache disabled
uint32_t zero2 : 7; // reserved
uint32_t pd_paddr : 20;
uint32_t zero1 : 3; // reserved
uint32_t write_through : 1; // 0 write-back - 1 write-through
uint32_t cache_disabled : 1; // 1=cache disabled
uint32_t zero2 : 7; // reserved
uint32_t pd_paddr : 20;
} __attribute__((packed));
// invalidate the TLB entry for the page located at the given virtual address
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)
{
struct pdbr cr3;
struct pdbr cr3;
// x86 got 1024 of pde for 4Byte each: 4ko !
struct pde *pd = (struct pde *)allocPhyPage();
// x86 got 1024 of pde for 4Byte each: 4ko !
struct pde *pd = (struct pde *)allocPhyPage();
memset(pd, 0, PAGE_SIZE);
memset(&cr3, 0x0, sizeof(struct pdbr));
memset(pd, 0, PAGE_SIZE);
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
// Identity mapping up to upperKernelAddr
for (paddr_t i = 0; i < upperKernelAddr; i += PAGE_SIZE) {
uint pdEntry = i >> (PD_SHIFT);
uint ptEntry = (i >> PT_SHIFT) & PTE_MASK;
struct pte *pt;
if (pd[pdEntry].present) {
pt = (struct pte *)(pd[pdEntry].pt_addr << PT_SHIFT);
refPhyPage((paddr_t)pt);
} else {
pt = (struct pte *)allocPhyPage();
// MMU not enabled for the moment. No need to use mirroring
// Identity mapping up to upperKernelAddr
for (paddr_t i = 0; i < upperKernelAddr; i += PAGE_SIZE) {
uint pdEntry = i >> (PD_SHIFT);
uint ptEntry = (i >> PT_SHIFT) & PTE_MASK;
struct pte *pt;
if (pd[pdEntry].present) {
pt = (struct pte *)(pd[pdEntry].pt_addr << PT_SHIFT);
refPhyPage((paddr_t)pt);
} else {
pt = (struct pte *)allocPhyPage();
memset(pt, 0, PAGE_SIZE);
pd[pdEntry].present = 1;
pd[pdEntry].write = 1;
pd[pdEntry].pt_addr = ((paddr_t)pt >> PT_SHIFT);
}
memset(pt, 0, PAGE_SIZE);
pd[pdEntry].present = 1;
pd[pdEntry].write = 1;
pd[pdEntry].pt_addr = ((paddr_t)pt >> PT_SHIFT);
}
pt[ptEntry].present = 1;
pt[ptEntry].write = 1; // TODO set Kernel code as RO
pt[ptEntry].paddr = i >> PAGE_SHIFT;
}
pt[ptEntry].present = 1;
pt[ptEntry].write = 1; // TODO set Kernel code as RO
pt[ptEntry].paddr = i >> PAGE_SHIFT;
}
// Setup mirroring
pd[PD_MIRROR_PAGE_IDX].present = 1;
pd[PD_MIRROR_PAGE_IDX].write = 1;
pd[PD_MIRROR_PAGE_IDX].pt_addr = ((paddr_t)pd >> PT_SHIFT);
// Setup mirroring
pd[PD_MIRROR_PAGE_IDX].present = 1;
pd[PD_MIRROR_PAGE_IDX].write = 1;
pd[PD_MIRROR_PAGE_IDX].pt_addr = ((paddr_t)pd >> PT_SHIFT);
// Loading of the PDBR in the MMU:
asm volatile("movl %0,%%cr3\n\t"
"movl %%cr0,%%eax\n\t"
"orl $0x80010000, %%eax\n\t" /* bit 31 | bit 16 */
"movl %%eax,%%cr0\n\t"
"jmp 1f\n\t"
"1:\n\t"
"movl $2f, %%eax\n\t"
"jmp *%%eax\n\t"
"2:\n\t" ::"r"(cr3)
: "memory", "eax");
return 0;
// Loading of the PDBR in the MMU:
asm volatile("movl %0,%%cr3\n\t"
"movl %%cr0,%%eax\n\t"
"orl $0x80010000, %%eax\n\t" /* bit 31 | bit 16 */
"movl %%eax,%%cr0\n\t"
"jmp 1f\n\t"
"1:\n\t"
"movl $2f, %%eax\n\t"
"jmp *%%eax\n\t"
"2:\n\t" ::"r"(cr3)
: "memory", "eax");
return 0;
}
int pageMap(vaddr_t vaddr, paddr_t paddr, int flags)
{
uint pdEntry = vaddr >> (PD_SHIFT);
uint ptEntry = (vaddr >> PT_SHIFT) & PTE_MASK;
uint pdEntry = vaddr >> (PD_SHIFT);
uint ptEntry = (vaddr >> PT_SHIFT) & PTE_MASK;
// Thank to mirroring, we can access the PD
struct pde *pd = (struct pde *)((PD_MIRROR_PAGE_IDX << PD_SHIFT) +
(PD_MIRROR_PAGE_IDX << PT_SHIFT));
// Thank to mirroring, we can access the PD
struct pde *pd =
(struct pde *)((PD_MIRROR_PAGE_IDX << PD_SHIFT) + (PD_MIRROR_PAGE_IDX << PT_SHIFT));
struct pte *pt =
(struct pte *)((PD_MIRROR_PAGE_IDX << PD_SHIFT) + (pdEntry << PT_SHIFT));
struct pte *pt = (struct pte *)((PD_MIRROR_PAGE_IDX << PD_SHIFT) + (pdEntry << PT_SHIFT));
if (!pd[pdEntry].present) {
paddr_t ptPhy = allocPhyPage();
if (ptPhy == (vaddr_t)NULL)
return -ENOMEM;
if (!pd[pdEntry].present) {
paddr_t ptPhy = allocPhyPage();
if (ptPhy == (vaddr_t)NULL)
return -ENOMEM;
pd[pdEntry].user = (flags & PAGING_MEM_USER) ? 1 : 0;
pd[pdEntry].present = 1;
pd[pdEntry].write = 1;
pd[pdEntry].pt_addr = (ptPhy >> PT_SHIFT);
pd[pdEntry].user = (flags & PAGING_MEM_USER) ? 1 : 0;
pd[pdEntry].present = 1;
pd[pdEntry].write = 1;
pd[pdEntry].pt_addr = (ptPhy >> PT_SHIFT);
__native_flush_tlb_single((vaddr_t)pt);
memset((void *)pt, 0, PAGE_SIZE);
} else {
__native_flush_tlb_single((vaddr_t)pt);
memset((void *)pt, 0, PAGE_SIZE);
} else {
// Already mapped ? Remove old mapping
if (pt[ptEntry].present) {
unrefPhyPage(pt[ptEntry].paddr << PAGE_SHIFT);
} // PTE not already used ? We will use it ! So increase the PT ref count
else {
refPhyPage(pd[pdEntry].pt_addr << PAGE_SHIFT);
}
}
// Already mapped ? Remove old mapping
if (pt[ptEntry].present) {
unrefPhyPage(pt[ptEntry].paddr << PAGE_SHIFT);
} // PTE not already used ? We will use it ! So increase the PT ref count
else {
refPhyPage(pd[pdEntry].pt_addr << PAGE_SHIFT);
}
}
pt[ptEntry].user = (flags & PAGING_MEM_USER) ? 1 : 0;
pt[ptEntry].present = 1;
pt[ptEntry].write = (flags & PAGING_MEM_WRITE) ? 1 : 0;
pt[ptEntry].paddr = paddr >> PAGE_SHIFT;
refPhyPage(paddr);
pt[ptEntry].user = (flags & PAGING_MEM_USER) ? 1 : 0;
pt[ptEntry].present = 1;
pt[ptEntry].write = (flags & PAGING_MEM_WRITE) ? 1 : 0;
pt[ptEntry].paddr = paddr >> PAGE_SHIFT;
refPhyPage(paddr);
__native_flush_tlb_single(vaddr);
mappedPage++;
return 0;
__native_flush_tlb_single(vaddr);
mappedPage++;
return 0;
}
int pageUnmap(vaddr_t vaddr)
{
uint pdEntry = vaddr >> (PD_SHIFT);
uint ptEntry = (vaddr >> PT_SHIFT) & PTE_MASK;
uint pdEntry = vaddr >> (PD_SHIFT);
uint ptEntry = (vaddr >> PT_SHIFT) & PTE_MASK;
// Thank to mirroring, we can access the PD
struct pde *pd = (struct pde *)((PD_MIRROR_PAGE_IDX << PD_SHIFT) +
(PD_MIRROR_PAGE_IDX << PT_SHIFT));
// Thank to mirroring, we can access the PD
struct pde *pd =
(struct pde *)((PD_MIRROR_PAGE_IDX << PD_SHIFT) + (PD_MIRROR_PAGE_IDX << PT_SHIFT));
struct pte *pt =
(struct pte *)((PD_MIRROR_PAGE_IDX << PD_SHIFT) + (pdEntry << PT_SHIFT));
if (!pd[pdEntry].present)
return -EINVAL;
if (!pt[ptEntry].present)
return -EINVAL;
struct pte *pt = (struct pte *)((PD_MIRROR_PAGE_IDX << PD_SHIFT) + (pdEntry << PT_SHIFT));
if (!pd[pdEntry].present)
return -EINVAL;
if (!pt[ptEntry].present)
return -EINVAL;
unrefPhyPage(pt[ptEntry].paddr << PAGE_SHIFT);
pt[ptEntry].present = 0;
unrefPhyPage(pt[ptEntry].paddr << PAGE_SHIFT);
pt[ptEntry].present = 0;
// PTE not used. Decrease refcount on it. Is PT not used anymore ?
if (unrefPhyPage(pd[pdEntry].pt_addr << PT_SHIFT) == 0) {
pd[pdEntry].present = 0;
__native_flush_tlb_single((vaddr_t)pt);
}
__native_flush_tlb_single(vaddr);
mappedPage--;
return 0;
// PTE not used. Decrease refcount on it. Is PT not used anymore ?
if (unrefPhyPage(pd[pdEntry].pt_addr << PT_SHIFT) == 0) {
pd[pdEntry].present = 0;
__native_flush_tlb_single((vaddr_t)pt);
}
__native_flush_tlb_single(vaddr);
mappedPage--;
return 0;
}
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
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
USA.
USA.
*/
#pragma once
@ -36,19 +36,15 @@
*
* @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_KDATA 2 /* Kernel data segment */
/**
* Helper macro that builds a segment register's value
*/
#define BUILD_SEGMENT_REG_VALUE(desc_privilege,in_ldt,seg_index) \
( (((desc_privilege) & 0x3) << 0) \
| (((in_ldt)?1:0) << 2) \
| ((seg_index) << 3) )
#define BUILD_SEGMENT_REG_VALUE(desc_privilege, in_ldt, seg_index) \
((((desc_privilege)&0x3) << 0) | (((in_ldt) ? 1 : 0) << 2) | ((seg_index) << 3))
/*
* Local segment selectors (LDT) for SOS/x86

View File

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

View File

@ -18,37 +18,37 @@ typedef unsigned long long __u64;
#endif
/* sysv */
typedef unsigned char unchar;
typedef unsigned short ushort;
typedef unsigned int uint;
typedef unsigned long ulong;
typedef unsigned char unchar;
typedef unsigned short ushort;
typedef unsigned int uint;
typedef unsigned long ulong;
typedef __s8 int8_t;
typedef __s16 int16_t;
typedef __s32 int32_t;
typedef __s8 int8_t;
typedef __s16 int16_t;
typedef __s32 int32_t;
typedef __u8 uint8_t;
typedef __u16 uint16_t;
typedef __u32 uint32_t;
typedef __u8 uint8_t;
typedef __u16 uint16_t;
typedef __u32 uint32_t;
typedef __u64 uint64_t;
typedef __u64 u_int64_t;
typedef __s64 int64_t;
typedef __u64 uint64_t;
typedef __u64 u_int64_t;
typedef __s64 int64_t;
typedef enum { FALSE=0, TRUE } bool_t;
#define NULL ((void*)0)
typedef enum { FALSE = 0, TRUE } bool_t;
#define NULL ((void *)0)
#if __x86_64__
typedef unsigned long size_t;
typedef long ssize_t;
typedef unsigned long int uintptr_t;
typedef unsigned long int uintptr_t;
#else
typedef unsigned int size_t;
typedef int ssize_t;
typedef unsigned int uintptr_t;
typedef unsigned int uintptr_t;
#endif
typedef void *va_list;
#define va_start(v, l) ((v) = (va_list) & (l) + sizeof(l))
#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
#define USHRT_MAX ((u16)(~0U))
#define SHRT_MAX ((s16)(USHRT_MAX>>1))
#define SHRT_MIN ((s16)(-SHRT_MAX - 1))
#define INT_MAX ((int)(~0U>>1))
#define INT_MIN (-INT_MAX - 1)
#define UINT_MAX (~0U)
#define LONG_MAX ((long)(~0UL>>1))
#define LONG_MIN (-LONG_MAX - 1)
#define ULONG_MAX (~0UL)
#define LLONG_MAX ((long long)(~0ULL>>1))
#define LLONG_MIN (-LLONG_MAX - 1)
#define ULLONG_MAX (~0ULL)
#define SIZE_MAX (~(size_t)0)
#define PHYS_ADDR_MAX (~(phys_addr_t)0)
#define USHRT_MAX ((u16)(~0U))
#define SHRT_MAX ((s16)(USHRT_MAX >> 1))
#define SHRT_MIN ((s16)(-SHRT_MAX - 1))
#define INT_MAX ((int)(~0U >> 1))
#define INT_MIN (-INT_MAX - 1)
#define UINT_MAX (~0U)
#define LONG_MAX ((long)(~0UL >> 1))
#define LONG_MIN (-LONG_MAX - 1)
#define ULONG_MAX (~0UL)
#define LLONG_MAX ((long long)(~0ULL >> 1))
#define LLONG_MIN (-LLONG_MAX - 1)
#define ULLONG_MAX (~0ULL)
#define SIZE_MAX (~(size_t)0)
#define PHYS_ADDR_MAX (~(phys_addr_t)0)
#define U8_MAX ((u8)~0U)
#define S8_MAX ((s8)(U8_MAX>>1))
#define S8_MIN ((s8)(-S8_MAX - 1))
#define U16_MAX ((u16)~0U)
#define S16_MAX ((s16)(U16_MAX>>1))
#define S16_MIN ((s16)(-S16_MAX - 1))
#define U32_MAX ((u32)~0U)
#define S32_MAX ((s32)(U32_MAX>>1))
#define S32_MIN ((s32)(-S32_MAX - 1))
#define U64_MAX ((u64)~0ULL)
#define S64_MAX ((s64)(U64_MAX>>1))
#define S64_MIN ((s64)(-S64_MAX - 1))
#define U8_MAX ((u8)~0U)
#define S8_MAX ((s8)(U8_MAX >> 1))
#define S8_MIN ((s8)(-S8_MAX - 1))
#define U16_MAX ((u16)~0U)
#define S16_MAX ((s16)(U16_MAX >> 1))
#define S16_MIN ((s16)(-S16_MAX - 1))
#define U32_MAX ((u32)~0U)
#define S32_MAX ((s32)(U32_MAX >> 1))
#define S32_MIN ((s32)(-S32_MAX - 1))
#define U64_MAX ((u64)~0ULL)
#define S64_MAX ((s64)(U64_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_MASK(x, mask) (((x) + (mask)) & ~(mask))

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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