Propagate page fault to ressource handler
Fix mmap arguments handling
This commit is contained in:
parent
78cf247cd4
commit
da266d19a3
@ -45,9 +45,9 @@ int exceptionSetRoutine(int exception, exception_handler handler)
|
|||||||
|
|
||||||
void print_handler(struct cpu_state *frame, ulong intr)
|
void print_handler(struct cpu_state *frame, ulong intr)
|
||||||
{
|
{
|
||||||
int intNbInt = intr;
|
VGAPrintf(RED, BLACK, 0, VGA_HEIGHT - 1, "EXCEPTION %lu", intr);
|
||||||
VGAPrintf(RED, BLACK, 0, VGA_HEIGHT - 1, "EXCEPTION %d", intNbInt);
|
|
||||||
printf("Exception %lu at 0x%p\n", intr, (void *)cpu_context_get_PC(frame));
|
printf("Exception %lu at 0x%p\n", intr, (void *)cpu_context_get_PC(frame));
|
||||||
|
|
||||||
asm("hlt");
|
asm("hlt");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -55,17 +55,26 @@ void pagefault_handler(struct cpu_state *frame, ulong intr)
|
|||||||
{
|
{
|
||||||
|
|
||||||
struct thread *current = getCurrentThread();
|
struct thread *current = getCurrentThread();
|
||||||
|
assert(frame == current->cpuState);
|
||||||
|
if (cpu_context_is_in_user_mode(current->cpuState)) {
|
||||||
struct uAddrSpace *as = processGetAddrSpace(current->process);
|
struct uAddrSpace *as = processGetAddrSpace(current->process);
|
||||||
vaddr_t faultAddr = cpu_context_get_EX_faulting_vaddr(frame);
|
vaddr_t faultAddr = cpu_context_get_EX_faulting_vaddr(frame);
|
||||||
|
|
||||||
if(!uAddrSpaceCheckNAlloc(as, faultAddr))
|
if (!uAddrSpaceHeapCheckNAlloc(as, faultAddr))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
printf("page fault while in thread [%s] at 0x%p when trying to access 0x%p err_code 0x%x\n", current->name,
|
// PAGE_FAULT is a interrupt with an error code (see exception_wrapper.S)
|
||||||
(void *)cpu_context_get_PC(frame), (void *)faultAddr, cpu_context_get_EX_err(frame));
|
uint32_t error_code = cpu_context_get_EX_err(frame);
|
||||||
if (cpu_context_is_in_user_mode(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");
|
printf("Killing User Thread\n");
|
||||||
threadExit();
|
threadExit();
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
VGAPrintf(RED, BLACK, 0, VGA_HEIGHT - 1, "PAGE FAULT %d", intr);
|
VGAPrintf(RED, BLACK, 0, VGA_HEIGHT - 1, "PAGE FAULT %d", intr);
|
||||||
(void)intr;
|
(void)intr;
|
||||||
@ -79,5 +88,6 @@ int exceptionSetup()
|
|||||||
exceptionSetRoutine(i, print_handler);
|
exceptionSetRoutine(i, print_handler);
|
||||||
}
|
}
|
||||||
exceptionSetRoutine(EXCEPTION_PAGE_FAULT, pagefault_handler);
|
exceptionSetRoutine(EXCEPTION_PAGE_FAULT, pagefault_handler);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -165,7 +165,7 @@
|
|||||||
iret
|
iret
|
||||||
.endm
|
.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
|
.irp exception_id, 8, 10, 11, 12, 13, 14, 17, 30
|
||||||
exception_mac_with_errcode exception_id
|
exception_mac_with_errcode exception_id
|
||||||
.endr
|
.endr
|
||||||
|
@ -61,6 +61,7 @@ int syscallExecute(int syscallId, const struct cpu_state *userCtx)
|
|||||||
case SYSCALL_ID_MMAP: {
|
case SYSCALL_ID_MMAP: {
|
||||||
struct uAddrSpace *as;
|
struct uAddrSpace *as;
|
||||||
uaddr_t uaddr;
|
uaddr_t uaddr;
|
||||||
|
uaddr_t uaddr_ptr;
|
||||||
size_t size;
|
size_t size;
|
||||||
uint32_t rights;
|
uint32_t rights;
|
||||||
uint32_t flags;
|
uint32_t flags;
|
||||||
@ -69,15 +70,26 @@ int syscallExecute(int syscallId, const struct cpu_state *userCtx)
|
|||||||
char path[256];
|
char path[256];
|
||||||
|
|
||||||
as = processGetAddrSpace(getCurrentThread()->process);
|
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);
|
(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));
|
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){
|
if(strcmp(path, "/dev/zero") == 0){
|
||||||
ret = zeroMmap(as, &uaddr, size, rights,flags);
|
ret = zeroMmap(as, &uaddr, size, rights,flags);
|
||||||
}
|
}
|
||||||
printf("ret %d\n", ret);
|
if(!ret){
|
||||||
(void)as;
|
if(memcpyToUser(uaddr_ptr, (vaddr_t)&uaddr, sizeof(uaddr)) != sizeof(uaddr)){
|
||||||
|
ret = -EFAULT;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
|
@ -44,6 +44,17 @@ static int memcpyUserMemNoCheck(vaddr_t dest, vaddr_t src, size_t size)
|
|||||||
return 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)
|
int memcpyFromUser(vaddr_t to, uaddr_t from, size_t size)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -4,4 +4,5 @@
|
|||||||
#include "stdarg.h"
|
#include "stdarg.h"
|
||||||
|
|
||||||
int memcpyFromUser(vaddr_t to, uaddr_t from, size_t size);
|
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);
|
int strzcpyFromUser(vaddr_t *to, uaddr_t *from, size_t size);
|
||||||
|
@ -250,7 +250,7 @@ uaddr_t sysBrk(struct uAddrSpace *as, uaddr_t newHeapTop)
|
|||||||
incSize = ALIGN(newHeapTop - (as->heapStart + as->heapSize), PAGE_SIZE);
|
incSize = ALIGN(newHeapTop - (as->heapStart + as->heapSize), PAGE_SIZE);
|
||||||
|
|
||||||
if (incSize < 0){
|
if (incSize < 0){
|
||||||
//TODO how to free allocated page by uAddrSpaceCheckNAlloc
|
//TODO how to free allocated page by uAddrSpaceHeapCheckNAlloc
|
||||||
return as->heapStart + as->heapSize;
|
return as->heapStart + as->heapSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -259,7 +259,7 @@ uaddr_t sysBrk(struct uAddrSpace *as, uaddr_t newHeapTop)
|
|||||||
return as->heapStart + as->heapSize;
|
return as->heapStart + as->heapSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
int uAddrSpaceCheckNAlloc(struct uAddrSpace *as, vaddr_t addr)
|
int uAddrSpaceHeapCheckNAlloc(struct uAddrSpace *as, vaddr_t addr)
|
||||||
{
|
{
|
||||||
struct uAddrVirtualReg *newReg;
|
struct uAddrVirtualReg *newReg;
|
||||||
int right = PAGING_MEM_USER | PAGING_MEM_WRITE | PAGING_MEM_READ;
|
int right = PAGING_MEM_USER | PAGING_MEM_WRITE | PAGING_MEM_READ;
|
||||||
@ -372,3 +372,28 @@ free_reg:
|
|||||||
free(reg);
|
free(reg);
|
||||||
return ret;
|
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;
|
||||||
|
}
|
||||||
|
@ -43,9 +43,10 @@ struct uAddrSpace * uAddrSpaceCreate(struct process *proc);
|
|||||||
int uAddrSpaceDelete(struct uAddrSpace *addr);
|
int uAddrSpaceDelete(struct uAddrSpace *addr);
|
||||||
struct mmu_context * uAddrSpaceGetMMUContext(struct uAddrSpace *addr);
|
struct mmu_context * uAddrSpaceGetMMUContext(struct uAddrSpace *addr);
|
||||||
int uAddrSpaceSetHeap(struct uAddrSpace *as, uaddr_t addr, size_t size);
|
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);
|
uaddr_t sysBrk(struct uAddrSpace *as, uaddr_t newHeapTop);
|
||||||
|
|
||||||
int uAddrSpaceMmap(struct uAddrSpace *as, uaddr_t *uaddr, size_t size, uint32_t rights,
|
int uAddrSpaceMmap(struct uAddrSpace *as, uaddr_t *uaddr, size_t size, uint32_t rights,
|
||||||
uint32_t flags, struct mappedRessource *res, uint32_t offset);
|
uint32_t flags, struct mappedRessource *res, uint32_t offset);
|
||||||
int uAddrSpaceUnmap(struct uAddrSpace *as, uaddr_t uaddr, size_t size);
|
int uAddrSpaceUnmap(struct uAddrSpace *as, uaddr_t uaddr, size_t size);
|
||||||
|
int uAddrSpaceSolvePageFault(struct uAddrSpace *as, vaddr_t faultAddr, int isWriteAccess);
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
#include "swintr.h"
|
#include "swintr.h"
|
||||||
#include "syscall.h"
|
#include "syscall.h"
|
||||||
|
|
||||||
|
int errno = 0;
|
||||||
int memcmp(const void *aptr, const void *bptr, size_t size)
|
int memcmp(const void *aptr, const void *bptr, size_t size)
|
||||||
{
|
{
|
||||||
const unsigned char *a = (const unsigned char *)aptr;
|
const unsigned char *a = (const unsigned char *)aptr;
|
||||||
@ -672,7 +673,11 @@ void free(void *ptr){
|
|||||||
blk->free = 1;
|
blk->free = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user