Fix bug that caused a crash if an interrupt was triggered while loading a binary.

This commit is contained in:
Ali Mashtizadeh 2014-12-30 21:13:29 -08:00
parent 9a4ad50d34
commit 907baa75a7

View File

@ -160,6 +160,65 @@ Loader_EnterUserLevel(void *arg)
Trap_Pop(&tf);
}
void
LoaderFileHelper(AS *as, VNode *vn, uintptr_t vaddr,
uintptr_t offset, uintptr_t len)
{
void *raddr;
if ((vaddr % PGSIZE) != 0) {
uintptr_t maxlen = PGSIZE - (vaddr % PGSIZE);
uintptr_t rlen = maxlen < len ? maxlen : len;
raddr = (void *)DMPA2VA(PMap_Translate(as, vaddr));
VFS_Read(vn, raddr, offset, rlen);
vaddr += rlen;
offset += rlen;
len -= rlen;
}
while (len > PGSIZE) {
raddr = (void *)DMPA2VA(PMap_Translate(as, vaddr));
VFS_Read(vn, raddr, offset, PGSIZE);
vaddr += PGSIZE;
offset += PGSIZE;
len -= PGSIZE;
}
if (len > 0) {
raddr = (void *)DMPA2VA(PMap_Translate(as, vaddr));
VFS_Read(vn, raddr, offset, len);
}
}
void
LoaderZeroHelper(AS *as, uintptr_t vaddr, uintptr_t len)
{
void *raddr;
if ((vaddr % PGSIZE) != 0) {
uintptr_t maxlen = PGSIZE - (vaddr % PGSIZE);
uintptr_t rlen = maxlen < len ? maxlen : len;
raddr = (void *)DMPA2VA(PMap_Translate(as, vaddr));
memset(raddr, 0, rlen);
vaddr += rlen;
len -= rlen;
}
while (len > PGSIZE) {
raddr = (void *)DMPA2VA(PMap_Translate(as, vaddr));
memset(raddr, 0, PGSIZE);
vaddr += PGSIZE;
len -= PGSIZE;
}
if (len > 0) {
raddr = (void *)DMPA2VA(PMap_Translate(as, vaddr));
memset(raddr, 0, len);
}
}
bool
Loader_Load(Thread *thr, VNode *vn, void *buf, uint64_t len)
{
@ -201,27 +260,23 @@ Loader_Load(Thread *thr, VNode *vn, void *buf, uint64_t len)
void *stack = PAlloc_AllocPage();
PMap_Map(as, (uint64_t)DMVA2PA(stack), 0x70000000, 1, 0);
PMap_LoadAS(as); // Reload CR3
for (i = 0; i < ehdr->e_phnum; i++)
{
ASSERT(phdr[i].p_type != PT_DYNAMIC);
if (phdr[i].p_type == PT_LOAD) {
if (phdr[i].p_filesz != 0) {
VFS_Read(vn, (void *)phdr[i].p_vaddr,
phdr[i].p_offset, phdr[i].p_filesz);
LoaderFileHelper(as, vn, phdr[i].p_vaddr,
phdr[i].p_offset, phdr[i].p_filesz);
}
memset((void *)(phdr[i].p_vaddr + phdr[i].p_filesz),
0,
(uintptr_t)(phdr[i].p_memsz - phdr[i].p_filesz));
LoaderZeroHelper(as,
phdr[i].p_vaddr + phdr[i].p_filesz,
phdr[i].p_memsz - phdr[i].p_filesz);
}
}
Thread_SetupKThread(thr, Loader_EnterUserLevel, (void *)ehdr->e_entry);
// Restore AS
PMap_LoadAS(Thread_Current()->space);
return true;
}