Propagate page fault to ressource handler

Fix mmap arguments handling
This commit is contained in:
Mathieu Maret 2024-02-04 21:42:29 +01:00 committed by Mathieu Maret
parent b9d741060f
commit d9051ea59c
8 changed files with 84 additions and 19 deletions

View File

@ -45,9 +45,9 @@ int exceptionSetRoutine(int exception, exception_handler handler)
void print_handler(struct cpu_state *frame, ulong intr)
{
int intNbInt = intr;
VGAPrintf(RED, BLACK, 0, VGA_HEIGHT - 1, "EXCEPTION %d", intNbInt);
VGAPrintf(RED, BLACK, 0, VGA_HEIGHT - 1, "EXCEPTION %lu", intr);
printf("Exception %lu at 0x%p\n", intr, (void *)cpu_context_get_PC(frame));
asm("hlt");
}
@ -55,17 +55,26 @@ void pagefault_handler(struct cpu_state *frame, ulong intr)
{
struct thread *current = getCurrentThread();
struct uAddrSpace *as = processGetAddrSpace(current->process);
vaddr_t faultAddr = cpu_context_get_EX_faulting_vaddr(frame);
assert(frame == current->cpuState);
if (cpu_context_is_in_user_mode(current->cpuState)) {
struct uAddrSpace *as = processGetAddrSpace(current->process);
vaddr_t faultAddr = cpu_context_get_EX_faulting_vaddr(frame);
if(!uAddrSpaceCheckNAlloc(as, faultAddr))
return;
if (!uAddrSpaceHeapCheckNAlloc(as, faultAddr))
return;
printf("page fault while in thread [%s] at 0x%p when trying to access 0x%p err_code 0x%x\n", current->name,
(void *)cpu_context_get_PC(frame), (void *)faultAddr, cpu_context_get_EX_err(frame));
if (cpu_context_is_in_user_mode(frame)) {
// PAGE_FAULT is a interrupt with an error code (see exception_wrapper.S)
uint32_t error_code = cpu_context_get_EX_err(frame);
if (!uAddrSpaceSolvePageFault(as, faultAddr, error_code & 0x2))
return;
printf(
"page fault while in thread [%s] at 0x%p when trying to access 0x%p err_code 0x%x\n",
current->name, (void *)cpu_context_get_PC(frame), (void *)faultAddr, error_code);
printf("Killing User Thread\n");
threadExit();
return;
}
VGAPrintf(RED, BLACK, 0, VGA_HEIGHT - 1, "PAGE FAULT %d", intr);
(void)intr;
@ -79,5 +88,6 @@ int exceptionSetup()
exceptionSetRoutine(i, print_handler);
}
exceptionSetRoutine(EXCEPTION_PAGE_FAULT, pagefault_handler);
return 0;
}

View File

@ -165,7 +165,7 @@
iret
.endm
/*List of exception w or w/o err codehttps://wiki.osdev.org/Exceptions*/
/* List of exception w or w/o err code https://wiki.osdev.org/Exceptions */
.irp exception_id, 8, 10, 11, 12, 13, 14, 17, 30
exception_mac_with_errcode exception_id
.endr

View File

@ -61,6 +61,7 @@ int syscallExecute(int syscallId, const struct cpu_state *userCtx)
case SYSCALL_ID_MMAP: {
struct uAddrSpace *as;
uaddr_t uaddr;
uaddr_t uaddr_ptr;
size_t size;
uint32_t rights;
uint32_t flags;
@ -69,15 +70,26 @@ int syscallExecute(int syscallId, const struct cpu_state *userCtx)
char path[256];
as = processGetAddrSpace(getCurrentThread()->process);
ret = syscallGet5args(userCtx, (unsigned int *)&uaddr, (unsigned int *)&size, (unsigned int *)&rights,
ret = syscallGet5args(userCtx, (unsigned int *)&uaddr_ptr, (unsigned int *)&size, (unsigned int *)&rights,
(unsigned int *)&flags, (unsigned int *)&userPath);
if (memcpyFromUser((vaddr_t)&uaddr, uaddr_ptr, sizeof(uaddr)) != sizeof(uaddr)) {
ret = -EFAULT;
break;
}
strzcpyFromUser((vaddr_t *)path, (uaddr_t *)userPath, sizeof(path));
printf("Trying mmap for device %s\n", path);
printf("Trying mmap for device %s at %lu\n", path, (vaddr_t)uaddr);
if(strcmp(path, "/dev/zero") == 0){
ret = zeroMmap(as, &uaddr, size, rights,flags);
}
printf("ret %d\n", ret);
(void)as;
if(!ret){
if(memcpyToUser(uaddr_ptr, (vaddr_t)&uaddr, sizeof(uaddr)) != sizeof(uaddr)){
ret = -EFAULT;
break;
}
}
break;
}
default:

View File

@ -44,6 +44,17 @@ static int memcpyUserMemNoCheck(vaddr_t dest, vaddr_t src, size_t size)
return size;
}
int memcpyToUser(uaddr_t to, vaddr_t from, size_t size)
{
if ((uint)to < PAGING_BASE_USER_ADDRESS)
return -EPERM;
if ((uint)to > PAGING_TOP_USER_ADDRESS - size)
return -EPERM;
return memcpyUserMemNoCheck(to, from, size);
}
int memcpyFromUser(vaddr_t to, uaddr_t from, size_t size)
{

View File

@ -4,4 +4,5 @@
#include "stdarg.h"
int memcpyFromUser(vaddr_t to, uaddr_t from, size_t size);
int memcpyToUser(uaddr_t to, vaddr_t from, size_t size);
int strzcpyFromUser(vaddr_t *to, uaddr_t *from, size_t size);

View File

@ -250,7 +250,7 @@ uaddr_t sysBrk(struct uAddrSpace *as, uaddr_t newHeapTop)
incSize = ALIGN(newHeapTop - (as->heapStart + as->heapSize), PAGE_SIZE);
if (incSize < 0){
//TODO how to free allocated page by uAddrSpaceCheckNAlloc
//TODO how to free allocated page by uAddrSpaceHeapCheckNAlloc
return as->heapStart + as->heapSize;
}
@ -259,7 +259,7 @@ uaddr_t sysBrk(struct uAddrSpace *as, uaddr_t newHeapTop)
return as->heapStart + as->heapSize;
}
int uAddrSpaceCheckNAlloc(struct uAddrSpace *as, vaddr_t addr)
int uAddrSpaceHeapCheckNAlloc(struct uAddrSpace *as, vaddr_t addr)
{
struct uAddrVirtualReg *newReg;
int right = PAGING_MEM_USER | PAGING_MEM_WRITE | PAGING_MEM_READ;
@ -372,3 +372,28 @@ free_reg:
free(reg);
return ret;
}
/**
* Check if @param faultAddr could be managed by the uAddrVirtualReg from @param as
**/
int uAddrSpaceSolvePageFault(struct uAddrSpace *as, vaddr_t faultAddr, int isWriteAccess)
{
struct uAddrVirtualReg *reg;
int rights = PAGING_MEM_READ;
reg = findVirtualRegionFromAddr(as, faultAddr, 1);
if (reg == NULL)
return -EFAULT;
if (isWriteAccess && !(reg->right & PAGING_MEM_WRITE))
return -EFAULT;
if (isWriteAccess)
rights |= PAGING_MEM_WRITE;
if (reg->res->ops->nopage(reg, faultAddr, rights))
return -EFAULT;
return 0;
}

View File

@ -43,9 +43,10 @@ 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);
int uAddrSpaceCheckNAlloc(struct uAddrSpace *as, vaddr_t addr);
int uAddrSpaceHeapCheckNAlloc(struct uAddrSpace *as, vaddr_t addr);
uaddr_t sysBrk(struct uAddrSpace *as, uaddr_t newHeapTop);
int uAddrSpaceMmap(struct uAddrSpace *as, uaddr_t *uaddr, size_t size, uint32_t rights,
uint32_t flags, struct mappedRessource *res, uint32_t offset);
int uAddrSpaceUnmap(struct uAddrSpace *as, uaddr_t uaddr, size_t size);
int uAddrSpaceSolvePageFault(struct uAddrSpace *as, vaddr_t faultAddr, int isWriteAccess);

View File

@ -4,6 +4,7 @@
#include "swintr.h"
#include "syscall.h"
int errno = 0;
int memcmp(const void *aptr, const void *bptr, size_t size)
{
const unsigned char *a = (const unsigned char *)aptr;
@ -725,7 +726,11 @@ void *realloc(void *ptr, size_t size)
return new_ptr;
}
void *mmap(void *addr, size_t len, int prot, int flags, char *path){
void *mmap(void *addr, size_t len, int prot, int flags, char *path) {
return (void *)syscall5(SYSCALL_ID_MMAP, (unsigned int)addr, len, prot, flags, (unsigned int)path);
int ret = syscall5(SYSCALL_ID_MMAP, (unsigned int)&addr, len, prot, flags, (unsigned int)path);
if(!ret)
return addr;
errno = ret;
return (void *)-1;
}