mirror of
https://github.com/drasko/codezero.git
synced 2026-01-12 02:43:15 +01:00
execve working from vfs executable file along with clone/fork/exit
This commit is contained in:
@@ -18,7 +18,7 @@
|
||||
#include INC_SUBARCH(mm.h)
|
||||
|
||||
/* Abort debugging conditions */
|
||||
#define DEBUG_ABORTS
|
||||
// #define DEBUG_ABORTS
|
||||
#if defined (DEBUG_ABORTS)
|
||||
#define dbg_abort(...) dprintk(__VA_ARGS__)
|
||||
#else
|
||||
|
||||
@@ -21,7 +21,6 @@ static inline void __attribute__ ((noreturn)) l4_exit(int status)
|
||||
|
||||
void __attribute__ ((noreturn)) _exit(int status)
|
||||
{
|
||||
printf("In %s.\n", __FUNCTION__);
|
||||
l4_exit(status);
|
||||
}
|
||||
|
||||
|
||||
@@ -8,6 +8,6 @@
|
||||
#define __EXIT_H__
|
||||
|
||||
void do_exit(struct tcb *task, int status);
|
||||
int execve_recycle_task(struct tcb *task);
|
||||
int execve_recycle_task(struct tcb *new, struct tcb *orig);
|
||||
|
||||
#endif /* __EXIT_H__ */
|
||||
|
||||
@@ -123,10 +123,7 @@ int do_execve(struct tcb *sender, char *filename, struct args_struct *args,
|
||||
/* Find the thread group leader of sender */
|
||||
BUG_ON(!(tgleader = find_task(sender->tgid)));
|
||||
|
||||
/*
|
||||
* Destroy all children threads.
|
||||
* TODO: Set up parents for children's children
|
||||
*/
|
||||
/* Destroy all children threads. */
|
||||
list_for_each_entry(thread, &tgleader->children, child_ref)
|
||||
do_exit(thread, 0);
|
||||
} else {
|
||||
@@ -134,18 +131,12 @@ int do_execve(struct tcb *sender, char *filename, struct args_struct *args,
|
||||
tgleader = sender;
|
||||
}
|
||||
|
||||
/* Copy data to new task that is to be retained from exec'ing task */
|
||||
new_task->tid = tgleader->tid;
|
||||
new_task->spid = tgleader->spid;
|
||||
new_task->tgid = tgleader->tgid;
|
||||
new_task->pagerid = tgleader->pagerid;
|
||||
new_task->utcb = tgleader->utcb;
|
||||
|
||||
/*
|
||||
* Copy data to be retained from exec'ing task to new one.
|
||||
* Release all task resources, do everything done in
|
||||
* exit() except destroying the actual thread.
|
||||
*/
|
||||
if ((err = execve_recycle_task(tgleader)) < 0) {
|
||||
if ((err = execve_recycle_task(new_task, tgleader)) < 0) {
|
||||
vm_file_put(vmfile);
|
||||
kfree(new_task);
|
||||
return err;
|
||||
|
||||
@@ -69,17 +69,36 @@ int task_close_files(struct tcb *task)
|
||||
}
|
||||
|
||||
/* Prepare old task's environment for new task */
|
||||
int execve_recycle_task(struct tcb *task)
|
||||
int execve_recycle_task(struct tcb *new, struct tcb *orig)
|
||||
{
|
||||
int err;
|
||||
struct task_ids ids = {
|
||||
.tid = task->tid,
|
||||
.spid = task->spid,
|
||||
.tgid = task->tgid,
|
||||
.tid = orig->tid,
|
||||
.spid = orig->spid,
|
||||
.tgid = orig->tgid,
|
||||
};
|
||||
|
||||
/*
|
||||
* Copy data to new task that is
|
||||
* to be retained from original
|
||||
*/
|
||||
|
||||
/* Copy ids */
|
||||
new->tid = orig->tid;
|
||||
new->spid = orig->spid;
|
||||
new->tgid = orig->tgid;
|
||||
new->pagerid = orig->pagerid;
|
||||
|
||||
/* Copy utcb */
|
||||
new->utcb = orig->utcb;
|
||||
|
||||
/* Copy parent relationship */
|
||||
BUG_ON(new->parent);
|
||||
new->parent = orig->parent;
|
||||
list_add(&new->child_ref, &orig->parent->children);
|
||||
|
||||
/* Flush all IO on task's files and close fds */
|
||||
task_close_files(task);
|
||||
task_close_files(orig);
|
||||
|
||||
/* Vfs still knows the thread */
|
||||
|
||||
@@ -88,12 +107,12 @@ int execve_recycle_task(struct tcb *task)
|
||||
/* Ask the kernel to recycle the thread */
|
||||
if ((err = l4_thread_control(THREAD_RECYCLE, &ids)) < 0) {
|
||||
printf("%s: Suspending thread %d failed with %d.\n",
|
||||
__FUNCTION__, task->tid, err);
|
||||
__FUNCTION__, orig->tid, err);
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Destroy the locally known tcb */
|
||||
tcb_destroy(task);
|
||||
tcb_destroy(orig);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -22,9 +22,14 @@
|
||||
|
||||
|
||||
/* Given a page and the vma it is in, returns that page's virtual address */
|
||||
unsigned long vma_page_to_virtual(struct vm_area *vma, struct page *p)
|
||||
unsigned long vma_page_to_virtual(struct vm_area *vma, struct page *page)
|
||||
{
|
||||
return __pfn_to_addr(vma->pfn_start + p->offset);
|
||||
unsigned long virtual_pfn = vma->pfn_start + page->offset - vma->file_offset;
|
||||
|
||||
/* Page must be contained in vma's pages */
|
||||
BUG_ON(vma->file_offset > page->offset);
|
||||
|
||||
return __pfn_to_addr(virtual_pfn);
|
||||
}
|
||||
|
||||
unsigned long fault_to_file_offset(struct fault_data *fault)
|
||||
|
||||
@@ -97,14 +97,23 @@ int task_insert_vma(struct vm_area *this, struct list_head *vma_list)
|
||||
BUG();
|
||||
}
|
||||
|
||||
/* Search an empty space in the task's mmapable address region. */
|
||||
/*
|
||||
* Search an empty space in the task's mmapable address region.
|
||||
*
|
||||
* This does a less than O(n) algorithm by starting the estimated region
|
||||
* and vma comparison from the beginning, once a vma is not intersected
|
||||
* that means it is an available slot. However if vma's and estimated
|
||||
* region does not go head-to-head for comparison, individual intersection
|
||||
* checks would be meaningless since any other vma could be intersecting.
|
||||
* Therefore head-to-head comparison is essential here.
|
||||
*/
|
||||
unsigned long find_unmapped_area(unsigned long npages, struct tcb *task)
|
||||
{
|
||||
unsigned long pfn_start = __pfn(task->map_start);
|
||||
unsigned long pfn_start = __pfn(task->start);
|
||||
unsigned long pfn_end = pfn_start + npages;
|
||||
struct vm_area *vma;
|
||||
|
||||
if (npages > __pfn(task->map_end - task->map_start))
|
||||
if (npages > __pfn(task->end - task->start))
|
||||
return 0;
|
||||
|
||||
/* If no vmas, first map slot is available. */
|
||||
|
||||
@@ -497,6 +497,12 @@ int task_mmap_segments(struct tcb *task, struct vm_file *file, struct exec_file_
|
||||
//struct vm_file *shm;
|
||||
int err;
|
||||
|
||||
/* Set up task's user boundary regions */
|
||||
task->start = USER_AREA_START;
|
||||
task->end = USER_AREA_END;
|
||||
task->map_start = task->start;
|
||||
task->map_end = task->end;
|
||||
|
||||
/* mmap task's text to task's address space. */
|
||||
if (IS_ERR(mapped = do_mmap(file, efd->text_offset, task, task->text_start,
|
||||
VM_READ | VM_WRITE | VM_EXEC | VMA_PRIVATE,
|
||||
|
||||
@@ -46,21 +46,21 @@ void main(void)
|
||||
pid = getpid();
|
||||
printf("Child: file IO test 1.\n");
|
||||
if (fileio() == 0)
|
||||
printf("-- PASSED --\n");
|
||||
printf("-- Fileio PASSED --\n");
|
||||
else
|
||||
printf("-- FAILED --\n");
|
||||
printf("-- Fileio FAILED --\n");
|
||||
|
||||
printf("Child: forktest.\n");
|
||||
if (forktest() == 0)
|
||||
printf("-- PASSED -- \n");
|
||||
printf("-- Fork PASSED -- \n");
|
||||
else
|
||||
printf("-- FAILED -- \n");
|
||||
printf("-- Fork FAILED -- \n");
|
||||
} else {
|
||||
printf("Parent: file IO test 2. child pid %d:\n", pid);
|
||||
if (fileio2() == 0)
|
||||
printf("-- PASSED --\n");
|
||||
printf("-- Fileio2 PASSED --\n");
|
||||
else
|
||||
printf("-- FAILED --\n");
|
||||
printf("-- Fileio2 FAILED --\n");
|
||||
}
|
||||
|
||||
printf("Testing clone syscall...\n");
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <tests.h>
|
||||
#include <l4/macros.h>
|
||||
|
||||
int global = 0;
|
||||
extern pid_t pid;
|
||||
@@ -39,5 +40,6 @@ int forktest(void)
|
||||
out:
|
||||
printf("PID: %d exiting...\n", myid);
|
||||
_exit(0);
|
||||
BUG();
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user