Implement brk syscall simple case

This commit is contained in:
Mathieu Maret 2022-08-09 16:15:00 +02:00
parent c59eb339e9
commit 6471ee9a2d
13 changed files with 204 additions and 3 deletions

View File

@ -3,6 +3,8 @@
#include "klibc.h" #include "klibc.h"
#include "mem.h" #include "mem.h"
#include "paging.h" #include "paging.h"
#include "thread.h"
#include "types.h"
/** /**
* Make sure the program is in a valid ELF format, map it into memory, * Make sure the program is in a valid ELF format, map it into memory,
@ -11,9 +13,10 @@
* @return 0 when the program is not a valid ELF * @return 0 when the program is not a valid ELF
*/ */
uaddr_t loadElfProg(const char *prog) uaddr_t loadElfProg(const char *prog, struct process * proc)
{ {
int i; int i;
uaddr_t lastUserAddr;
/** /**
* Typedefs, constants and structure definitions as given by the ELF * Typedefs, constants and structure definitions as given by the ELF
@ -176,7 +179,12 @@ uaddr_t loadElfProg(const char *prog)
/* Copy segment into memory */ /* Copy segment into memory */
memcpy((void *)elf_phdrs[i].p_vaddr, (void *)(prog + elf_phdrs[i].p_offset), memcpy((void *)elf_phdrs[i].p_vaddr, (void *)(prog + elf_phdrs[i].p_offset),
elf_phdrs[i].p_filesz); elf_phdrs[i].p_filesz);
if (lastUserAddr < uaddr) {
lastUserAddr = uaddr;
}
} }
processInitHeap(proc, lastUserAddr);
return elf_hdr->e_entry; return elf_hdr->e_entry;
} }

View File

@ -1,4 +1,6 @@
#pragma once #pragma once
#include "process.h"
#include "thread.h"
#include "types.h" #include "types.h"
uaddr_t loadElfProg(const char *prog); uaddr_t loadElfProg(const char *prog, struct process *proc);

View File

@ -86,7 +86,7 @@ void loadUserSpace()
struct process *proc = processCreate("UserSpace"); struct process *proc = processCreate("UserSpace");
threadChangeCurrentContext(processGetMMUContext(proc)); threadChangeCurrentContext(processGetMMUContext(proc));
uaddr_t prog = loadElfProg(buf + FILE_HEADER_SIZE); uaddr_t prog = loadElfProg(buf + FILE_HEADER_SIZE, proc);
if (prog == (uaddr_t)NULL) { if (prog == (uaddr_t)NULL) {
free(buf); free(buf);
return; return;

View File

@ -4,6 +4,7 @@
#include "klibc.h" #include "klibc.h"
#include "list.h" #include "list.h"
#include "mmuContext.h" #include "mmuContext.h"
#include "types.h"
#include "uaddrspace.h" #include "uaddrspace.h"
struct process { struct process {
@ -167,3 +168,11 @@ struct mmu_context *processGetMMUContext(struct process *proc)
{ {
return uAddrSpaceGetMMUContext(proc->addrSpace); return uAddrSpaceGetMMUContext(proc->addrSpace);
} }
struct uAddrSpace *processGetAddrSpace(struct process *proc){
return proc->addrSpace;
}
int processInitHeap(struct process *proc, uaddr_t lastUserAddr){
return uAddrSpaceSetHeap(proc->addrSpace, lastUserAddr, 0);
}

View File

@ -15,3 +15,5 @@ int processSetName(struct process *proc, char *name);
int processAddThread(struct process *proc, struct thread *th); int processAddThread(struct process *proc, struct thread *th);
int processRemoveThread(struct thread *th); int processRemoveThread(struct thread *th);
struct mmu_context *processGetMMUContext(struct process *th); struct mmu_context *processGetMMUContext(struct process *th);
struct uAddrSpace *processGetAddrSpace(struct process *proc);
int processInitHeap(struct process *proc, uaddr_t lastUserAddr);

View File

@ -1,8 +1,11 @@
#include "syscall.h" #include "syscall.h"
#include "keyboard.h" #include "keyboard.h"
#include "klibc.h" #include "klibc.h"
#include "process.h"
#include "stdarg.h" #include "stdarg.h"
#include "thread.h" #include "thread.h"
#include "types.h"
#include "uaddrspace.h"
int syscallExecute(int syscallId, const struct cpu_state *userCtx) int syscallExecute(int syscallId, const struct cpu_state *userCtx)
{ {
@ -37,6 +40,21 @@ int syscallExecute(int syscallId, const struct cpu_state *userCtx)
printf("Got 5args from userspace %d %d %d %d %d\n", arg1, arg2, arg3, arg4, arg5); printf("Got 5args from userspace %d %d %d %d %d\n", arg1, arg2, arg3, arg4, arg5);
break; break;
} }
case SYSCALL_ID_BRK:{
struct uAddrSpace *as;
uaddr_t newHeapTop;
as = processGetAddrSpace(getCurrentThread()->process);
ret = syscallGet1arg(userCtx, (unsigned int *)&newHeapTop);
if (ret != 0)
break;
threadChangeCurrentContext(uAddrSpaceGetMMUContext(as));
//TODO : what if *newHeapTop raise page fault?
ret = sysBrk(as, newHeapTop);
threadChangeCurrentContext(NULL);
break;
}
default: default:
printf("Unknon syscall id %d\n", syscallId); printf("Unknon syscall id %d\n", syscallId);
ret = -ENOENT; ret = -ENOENT;

View File

@ -8,6 +8,7 @@
#define SYSCALL_ID_PUTC 3 #define SYSCALL_ID_PUTC 3
#define SYSCALL_ID_READ 4 #define SYSCALL_ID_READ 4
#define SYSCALL_ID_TEST 5 #define SYSCALL_ID_TEST 5
#define SYSCALL_ID_BRK 6
#ifdef __KERNEL__ #ifdef __KERNEL__
int syscallExecute(int syscallId, const struct cpu_state *user_ctx); int syscallExecute(int syscallId, const struct cpu_state *user_ctx);

119
core/uaddrspace.c Normal file
View File

@ -0,0 +1,119 @@
#include "uaddrspace.h"
#include "alloc.h"
#include "kernel.h"
#include "mem.h"
#include "mmuContext.h"
#include "process.h"
#include "stdarg.h"
#include "thread.h"
#include "types.h"
#include <assert.h>
#include <stddef.h>
#include <stdint.h>
struct uAddrVirtualReg {
uaddr_t addr;
size_t size;
int right; // PAGING_MEM_*
uint32_t offset; // in the mappedRessource
uint flags;
struct mappedRessource *res;
struct uAddrVirtualReg *nextInAddrSpace, *prevInAddrSpace;
struct uAddrVirtualReg *nextInMappedRes, *prevInMappedRes;
};
struct uAddrSpace {
struct process *process; // The process that is represented by this AS
struct mmu_context *ctx; // The corresponding MMU configuration
struct uAddrVirtualReg *listVirtualReg; // List of Virtual Region used by this process
uaddr_t heapStart; // Start of the Head
size_t heapSize; // Hep size -> modified by brk()
};
struct mappedRessourceOps {
int (*open)(struct uAddrVirtualReg *vreg);
int (*close)(struct uAddrVirtualReg *vreg);
int (*unmap)(struct uAddrVirtualReg *vregi, uaddr_t addr, size_t size);
int (*nopage)(struct uAddrVirtualReg *vregi, uaddr_t addr,
int right); // Called by the pageflt handler when the page is missing
};
struct mappedRessource {
int right; // PAGING_MEM_*
struct mappedRessourceOps *ops;
struct uAddrVirtualReg *listVirtualReg;
};
struct uAddrSpace *uAddrSpaceCreate(struct process *proc)
{
struct uAddrSpace *addr = (struct uAddrSpace *)malloc(sizeof(struct uAddrSpace));
if (addr == NULL)
return NULL;
addr->ctx = mmuContextCreate();
if (addr->ctx == NULL) {
free(addr);
return NULL;
}
addr->process = proc;
return addr;
}
int uAddrSpaceDelete(struct uAddrSpace *addr)
{
// TODO Work on Virtual Region
return mmuContextUnref(addr->ctx);
}
struct mmu_context *uAddrSpaceGetMMUContext(struct uAddrSpace *addr)
{
return addr->ctx;
}
int uAddrSpaceSetHeap(struct uAddrSpace *as, uaddr_t addr, size_t size)
{
as->heapStart = addr;
as->heapSize = size;
return 0;
}
uaddr_t sysBrk(struct uAddrSpace *as, uaddr_t newHeapTop)
{
int incSize;
assert(as->heapStart);
if (!newHeapTop || newHeapTop < as->heapStart)
return as->heapStart + as->heapSize;
newHeapTop = ALIGN(newHeapTop, PAGE_SIZE);
if (newHeapTop == as->heapStart + as->heapSize)
return newHeapTop;
incSize = ALIGN(newHeapTop - (as->heapStart + as->heapSize), PAGE_SIZE);
if (incSize < 0){
//FIXME
return as->heapStart + as->heapSize;
}
//WIP do it manually
for (uaddr_t begin = ALIGN(as->heapStart + as->heapSize, PAGE_SIZE); begin < newHeapTop; begin += PAGE_SIZE) {
paddr_t ppage = allocPhyPage(1);
if (0 != pageMap(begin, ppage,
PAGING_MEM_USER | PAGING_MEM_WRITE | PAGING_MEM_READ))
return (uaddr_t)NULL;
unrefPhyPage(ppage);
}
return 0;
}

14
core/uaddrspace.h Normal file
View File

@ -0,0 +1,14 @@
#pragma once
#include "mmuContext.h"
#include "process.h"
#include "types.h"
#include <stddef.h>
struct uAddrSpace;
struct uAddrVirtualReg;
struct uAddrSpace * uAddrSpaceCreate(struct process *proc);
int uAddrSpaceDelete(struct uAddrSpace *addr);
struct mmu_context * uAddrSpaceGetMMUContext(struct uAddrSpace *addr);
int uAddrSpaceSetHeap(struct uAddrSpace *as, uaddr_t addr, size_t size);
uaddr_t sysBrk(struct uAddrSpace *as, uaddr_t newHeapTop);

View File

@ -8,6 +8,7 @@
#define SYSCALL_ID_PUTC 3 #define SYSCALL_ID_PUTC 3
#define SYSCALL_ID_READ 4 #define SYSCALL_ID_READ 4
#define SYSCALL_ID_TEST 5 #define SYSCALL_ID_TEST 5
#define SYSCALL_ID_BRK 6
#ifdef __KERNEL__ #ifdef __KERNEL__
int syscallExecute(int syscallId, const struct cpu_state *user_ctx); int syscallExecute(int syscallId, const struct cpu_state *user_ctx);

View File

@ -566,3 +566,7 @@ int readline(char *buf, int size)
return i == (size-1); return i == (size-1);
} }
void *brk(void *addr)
{
return (void *)syscall1(SYSCALL_ID_BRK, (unsigned int)addr);
}

View File

@ -45,3 +45,4 @@ int testSycall5(uint arg1, uint arg2, uint arg3, uint arg4, uint arg5);
char readc(); char readc();
char readcBlock(); char readcBlock();
int readline(char *buf, int size); int readline(char *buf, int size);
void *brk(void *addr);

View File

@ -13,6 +13,7 @@ int func_help()
printf(" suicide\n"); printf(" suicide\n");
printf(" help\n"); printf(" help\n");
printf(" syscall5\n"); printf(" syscall5\n");
printf(" alloc\n");
return 0; return 0;
} }
@ -24,6 +25,23 @@ int func_suicide()
return 0; return 0;
} }
void * initialHeap = 0;
int func_alloc(){
if(initialHeap == 0){
initialHeap = brk(0);
}
void * currentHeap = brk(0);
if (currentHeap - initialHeap < 4096){
brk(initialHeap + 4096);
}
int * allocatedData = (int *)initialHeap;
for(unsigned int i = 0 ; i < 4096/sizeof(int); i++){
allocatedData[i] =i;
}
return 0;
}
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
(void)argc; (void)argc;
@ -50,6 +68,10 @@ int main(int argc, char *argv[])
testSycall5(1, 2, 3, 4, 5); testSycall5(1, 2, 3, 4, 5);
continue; continue;
} }
if (strcmp(buf, "alloc") == 0) {
func_alloc();
continue;
}
} }
return 0; return 0;
} }