Skip to content

Commit

Permalink
kernel
Browse files Browse the repository at this point in the history
  • Loading branch information
ozkl committed Dec 9, 2017
1 parent b10b097 commit acc429f
Show file tree
Hide file tree
Showing 72 changed files with 31,270 additions and 0 deletions.
26 changes: 26 additions & 0 deletions Makefile
@@ -0,0 +1,26 @@
SOURCES_C=$(patsubst %.c,%.o,$(wildcard kernel/*.c))
SOURCES_ASM=$(patsubst %.asm,%.o,$(wildcard kernel/*.asm))


CC=cc
LD=ld
REDZONE=-mno-red-zone
CFLAGS=-nostdlib -nostdinc -fno-builtin -m32 -c
LDFLAGS=-Tlink.ld -m elf_i386
ASFLAGS=-felf

OBJ = $(SOURCES_ASM) $(SOURCES_C)

all: $(OBJ) link

clean:
-rm kernel/*.o kernel.bin

link:
$(LD) $(LDFLAGS) -o kernel.bin $(OBJ)

kernel/%.o:kernel/%.c
$(CC) $(CFLAGS) $< -o $@

kernel/%.o:kernel/%.asm
nasm $(ASFLAGS) $< -o $@
13 changes: 13 additions & 0 deletions bootdisk-root/boot/grub/grub.cfg
@@ -0,0 +1,13 @@
menuentry "SOSO DISK" {
set root=(hd0,1)
multiboot /boot/kernel
module /boot/initrd.img
boot
}

menuentry "SOSO CD" {
set root=(cd)
multiboot /boot/kernel
module /boot/initrd.img
boot
}
250 changes: 250 additions & 0 deletions kernel/alloc.c
@@ -0,0 +1,250 @@
#include "common.h"
#include "screen.h"
#include "alloc.h"
#include "vmm.h"
#include "process.h"
#include "debugprint.h"

#define KMALLOC_MINSIZE 16

extern uint32 *gKernelPageDirectory;

static char *gKernelHeap = NULL;
static uint32 gKernelHeapUsed = 0;


void initializeKernelHeap()
{
gKernelHeap = (char *) KERN_HEAP_BEGIN;

ksbrkPage(1);
}

void *ksbrkPage(int n)
{
struct MallocHeader *chunk;
char *p_addr;
int i;

if ((gKernelHeap + (n * PAGESIZE_4M)) > (char *) KERN_HEAP_END) {
Screen_PrintF("ERROR: ksbrk(): no virtual memory left for kernel heap !\n");
return (char *) -1;
}

chunk = (struct MallocHeader *) gKernelHeap;

for (i = 0; i < n; i++)
{
p_addr = getPageFrame4M();

//Screen_PrintF("DEBUG: ksbrkPage(): got 4M on physical %x\n", p_addr);

if ((int)(p_addr) < 0)
{
PANIC("PANIC: ksbrkPage(): no free page frame available !");
return (char *) -1;
}

addPageToPd(gKernelPageDirectory, gKernelHeap, p_addr, /*0*/PG_USER); //PG_USER for now to allow user programs to read kernel heap

gKernelHeap += PAGESIZE_4M;
}

chunk->size = PAGESIZE_4M * n;
chunk->used = 0;

return chunk;
}

void *kmalloc(uint32 size)
{
if (size==0)
return 0;

unsigned long realsize;
struct MallocHeader *chunk, *other;

if ((realsize = sizeof(struct MallocHeader) + size) < KMALLOC_MINSIZE)
{
realsize = KMALLOC_MINSIZE;
}

chunk = (struct MallocHeader *) KERN_HEAP_BEGIN;
while (chunk->used || chunk->size < realsize)
{
if (chunk->size == 0)
{
Screen_PrintF("\nPANIC: kmalloc(): corrupted chunk on %x with null size (heap %x) !\nSystem halted\n", chunk, gKernelHeap);

PANIC("kmalloc()");

return 0;
}

chunk = (struct MallocHeader *)((char *)chunk + chunk->size);

if (chunk == (struct MallocHeader *) gKernelHeap)
{
if ((int)(ksbrkPage((realsize / PAGESIZE_4M) + 1)) < 0)
{
PANIC("kmalloc(): no memory left for kernel !\nSystem halted\n");

return 0;
}
}
else if (chunk > (struct MallocHeader *) gKernelHeap)
{
Screen_PrintF("\nPANIC: kmalloc(): chunk on %x while heap limit is on %x !\nSystem halted\n", chunk, gKernelHeap);

PANIC("kmalloc()");

return 0;
}
}


if (chunk->size - realsize < KMALLOC_MINSIZE)
{
chunk->used = 1;
}
else
{
other = (struct MallocHeader *)((char *) chunk + realsize);
other->size = chunk->size - realsize;
other->used = 0;

chunk->size = realsize;
chunk->used = 1;
}

gKernelHeapUsed += realsize;

return (char *) chunk + sizeof(struct MallocHeader);
}

void kfree(void *v_addr)
{
if (v_addr==(void*)0)
return;

struct MallocHeader *chunk, *other;

chunk = (struct MallocHeader *)((uint32)v_addr - sizeof(struct MallocHeader));
chunk->used = 0;

gKernelHeapUsed -= chunk->size;

//Merge free block with next free block
while ((other = (struct MallocHeader *)((char *)chunk + chunk->size))
&& other < (struct MallocHeader *)gKernelHeap
&& other->used == 0)
{
chunk->size += other->size;
}
}

static void sbrkPage(Process* process, int pageCount)
{
if (pageCount > 0)
{
for (int i = 0; i < pageCount; ++i)
{
char * p_addr = getPageFrame4M();

if ((int)(p_addr) < 0)
{
PANIC("sbrkPage(): no free page frame available !");
return;
}

addPageToPd(process->pd, process->heapNextUnallocatedPageBegin, p_addr, PG_USER);

process->heapNextUnallocatedPageBegin += PAGESIZE_4M;
}
}
else if (pageCount < 0)
{
pageCount *= -1;

for (int i = 0; i < pageCount; ++i)
{
if (process->heapNextUnallocatedPageBegin - PAGESIZE_4M >= process->heapBegin)
{
process->heapNextUnallocatedPageBegin -= PAGESIZE_4M;

//This also releases the page frame
removePageFromPd(process->pd, process->heapNextUnallocatedPageBegin);
}
}
}
}

void initializeProcessHeap(Process* process)
{
process->heapBegin = (char*) USER_OFFSET;
process->heapEnd = process->heapBegin;
process->heapNextUnallocatedPageBegin = process->heapBegin;

//Userland programs (their code, data,..) start from USER_OFFSET
//So we should leave some space for them by moving heap pointer.
//As a result userspace malloc functions start from a forward point (+ USER_EXE_IMAGE).

sbrk(process, USER_EXE_IMAGE);
}

void *sbrk(Process* process, int nBytes)
{
//Screen_PrintF("sbrk:1: pid:%d nBytes:%d\n", process->pid, nBytes);

char* previousBreak = process->heapEnd;

if (nBytes > 0)
{
int remainingInThePage = process->heapNextUnallocatedPageBegin - process->heapEnd;

//Screen_PrintF("sbrk:2: remainingInThePage:%d\n", remainingInThePage);

if (nBytes > remainingInThePage)
{
int bytesNeededInNewPages = nBytes - remainingInThePage;
int neededNewPageCount = (bytesNeededInNewPages / PAGESIZE_4M) + 1;

//Screen_PrintF("sbrk:3: neededNewPageCount:%d\n", neededNewPageCount);

uint32 freePages = getFreePageCount();
if ((uint32)neededNewPageCount + 1 > freePages)
{
return (void*)-1;
}

sbrkPage(process, neededNewPageCount);
}
}
else if (nBytes < 0)
{
char* currentPageBegin = process->heapNextUnallocatedPageBegin - PAGESIZE_4M;

int remainingInThePage = process->heapEnd - currentPageBegin;

//Screen_PrintF("sbrk:4: remainingInThePage:%d\n", remainingInThePage);

if (-nBytes > remainingInThePage)
{
int bytesInPreviousPages = -nBytes - remainingInThePage;
int neededNewPageCount = (bytesInPreviousPages / PAGESIZE_4M) + 1;

//Screen_PrintF("sbrk:5: neededNewPageCount:%d\n", neededNewPageCount);

sbrkPage(process, -neededNewPageCount);
}
}

process->heapEnd += nBytes;

return previousBreak;
}

uint32 getKernelHeapUsed()
{
return gKernelHeapUsed;
}
25 changes: 25 additions & 0 deletions kernel/alloc.h
@@ -0,0 +1,25 @@
#ifndef ALLOC_H
#define ALLOC_H

#include "common.h"
#include "process.h"

void initializeKernelHeap();
void *ksbrkPage(int n);
void *kmalloc(uint32 size);
void kfree(void *v_addr);

void initializeProcessHeap(Process* process);
void *sbrk(Process* process, int nBytes);

uint32 getKernelHeapUsed();

struct MallocHeader
{
unsigned long size:31;
unsigned long used:1;
} __attribute__ ((packed));

typedef struct MallocHeader MallocHeader;

#endif // ALLOC_H
41 changes: 41 additions & 0 deletions kernel/boot.asm
@@ -0,0 +1,41 @@
MBOOT_PAGE_ALIGN equ 1<<0
MBOOT_MEM_INFO equ 1<<1
MBOOT_HEADER_MAGIC equ 0x1BADB002
MBOOT_HEADER_FLAGS equ MBOOT_PAGE_ALIGN | MBOOT_MEM_INFO
MBOOT_CHECKSUM equ -(MBOOT_HEADER_MAGIC + MBOOT_HEADER_FLAGS)


[BITS 32]


section .multiboot
align 4
dd MBOOT_HEADER_MAGIC
dd MBOOT_HEADER_FLAGS
dd MBOOT_CHECKSUM


section .bss
align 16
stack_bottom:
resb 16384 ; 16 KiB
stack_top:

[GLOBAL _start] ; this is the entry point. we tell linker script to set start address of kernel elf file.
[EXTERN kmain]

section .text

_start:
mov esp, stack_top

; push multiboot parameter to kmain()
push ebx

; ...and run!
cli
call kmain

;never reach here
cli
hlt

0 comments on commit acc429f

Please sign in to comment.