mirror of
https://github.com/drasko/codezero.git
synced 2026-01-12 02:43:15 +01:00
sys_write() "seems to" work. Also added support for sys_lseek().
This commit is contained in:
@@ -20,7 +20,7 @@ static inline off_t l4_lseek(int fildes, off_t offset, int whence)
|
||||
write_mr(L4SYS_ARG2, whence);
|
||||
|
||||
/* Call pager with shmget() request. Check ipc error. */
|
||||
if ((offres = l4_sendrecv(VFS_TID, VFS_TID, L4_IPC_TAG_LSEEK)) < 0) {
|
||||
if ((offres = l4_sendrecv(PAGER_TID, PAGER_TID, L4_IPC_TAG_LSEEK)) < 0) {
|
||||
printf("%s: L4 IPC Error: %d.\n", __FUNCTION__, offres);
|
||||
return offres;
|
||||
}
|
||||
|
||||
@@ -213,6 +213,8 @@ struct page *page_init(struct page *page);
|
||||
|
||||
/* To get currently mapped page of a virtual address on a task */
|
||||
struct page *task_virt_to_page(struct tcb *t, unsigned long virtual);
|
||||
int validate_task_range(struct tcb *t, unsigned long start,
|
||||
unsigned long end, unsigned int vmflags);
|
||||
|
||||
/* Main page fault entry point */
|
||||
int page_fault_handler(l4id_t tid, fault_kdata_t *fkdata);
|
||||
|
||||
@@ -97,6 +97,10 @@ void handle_requests(void)
|
||||
sys_write(sender, (int)mr[0], (void *)mr[1], (int)mr[2]);
|
||||
break;
|
||||
|
||||
case L4_IPC_TAG_LSEEK:
|
||||
sys_lseek(sender, (int)mr[0], (off_t)mr[1], (int)mr[2]);
|
||||
break;
|
||||
|
||||
case L4_IPC_TAG_MMAP2: {
|
||||
struct sys_mmap_args *args = (struct sys_mmap_args *)mr[0];
|
||||
sys_mmap(sender, args->start, args->length, args->prot,
|
||||
|
||||
@@ -231,7 +231,7 @@ struct vm_obj_link *vma_create_shadow(void)
|
||||
}
|
||||
|
||||
/* Allocates a new page, copies the original onto it and returns. */
|
||||
struct page *copy_page(struct page *orig)
|
||||
struct page *copy_to_new_page(struct page *orig)
|
||||
{
|
||||
void *new_vaddr, *vaddr, *paddr;
|
||||
struct page *new;
|
||||
@@ -349,7 +349,7 @@ struct page *copy_on_write(struct fault_data *fault)
|
||||
* Copy the page. This traverse and copy is like a page-in operation
|
||||
* of a pager, except that the page is moving along vm_objects.
|
||||
*/
|
||||
new_page = copy_page(page);
|
||||
new_page = copy_to_new_page(page);
|
||||
|
||||
/* Update page details */
|
||||
spin_lock(&new_page->lock);
|
||||
@@ -929,6 +929,28 @@ int page_fault_handler(l4id_t sender, fault_kdata_t *fkdata)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Checks if an address range is a validly mapped area for a task */
|
||||
int validate_task_range(struct tcb *t, unsigned long start,
|
||||
unsigned long end, unsigned int vmflags)
|
||||
{
|
||||
struct vm_area *vma;
|
||||
|
||||
start = page_align(start);
|
||||
end = page_align_up(end);
|
||||
|
||||
/* Find the vma that maps that virtual address */
|
||||
for (unsigned long vaddr = start; vaddr < end; vaddr += PAGE_SIZE) {
|
||||
if (!(vma = find_vma(vaddr, &t->vm_area_list))) {
|
||||
printf("%s: No VMA found for 0x%x on task: %d\n",
|
||||
__FUNCTION__, vaddr, t->tid);
|
||||
return -EINVAL;
|
||||
}
|
||||
if ((vma->flags & vmflags) != vmflags)
|
||||
return -EINVAL;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Makes the virtual to page translation for a given user task.
|
||||
* It traverses the vm_objects and returns the first encountered
|
||||
@@ -979,8 +1001,8 @@ struct page *task_virt_to_page(struct tcb *t, unsigned long virtual)
|
||||
}
|
||||
|
||||
/* Found it */
|
||||
printf("%s: %s: Found page with file_offset: 0x%x. vm object:\n",
|
||||
__TASKNAME__, __FUNCTION__, (unsigned long)page, page->offset);
|
||||
// printf("%s: %s: Found page with file_offset: 0x%x\n",
|
||||
// __TASKNAME__, __FUNCTION__, page->offset);
|
||||
vm_object_print(vmo_link->obj);
|
||||
|
||||
return page;
|
||||
|
||||
@@ -18,6 +18,25 @@
|
||||
/* List of all generic files */
|
||||
LIST_HEAD(vm_file_list);
|
||||
|
||||
|
||||
/* Copy from one page's buffer into another page */
|
||||
int page_copy(struct page *dst, struct page *src,
|
||||
unsigned long offset, unsigned long size)
|
||||
{
|
||||
void *dstvaddr, *srcvaddr;
|
||||
|
||||
BUG_ON(offset + size > PAGE_SIZE);
|
||||
dstvaddr = l4_map_helper((void *)page_to_phys(dst), 1);
|
||||
srcvaddr = l4_map_helper((void *)page_to_phys(src), 1);
|
||||
|
||||
memcpy(dstvaddr + offset, srcvaddr + offset, size);
|
||||
|
||||
l4_unmap_helper(dstvaddr, 1);
|
||||
l4_unmap_helper(srcvaddr, 1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int vfs_read(unsigned long vnum, unsigned long file_offset,
|
||||
unsigned long npages, void *pagebuf)
|
||||
{
|
||||
@@ -340,12 +359,12 @@ int vfs_write(unsigned long vnum, unsigned long file_offset,
|
||||
*/
|
||||
|
||||
/* Writes user data in buffer into pages in cache */
|
||||
int write_cache_pages(struct vm_file *vmfile, void *buf, unsigned long pfn_start,
|
||||
unsigned long pfn_end, unsigned long cursor_offset, int count)
|
||||
int write_cache_pages(struct vm_file *vmfile, struct tcb *task, void *buf,
|
||||
unsigned long pfn_start, unsigned long pfn_end,
|
||||
unsigned long cursor_offset, int count)
|
||||
{
|
||||
struct page *head, *this;
|
||||
int copysize, left;
|
||||
void *page_virtual;
|
||||
unsigned long last_offset; /* Last copied page's offset */
|
||||
|
||||
/* Find the head of consecutive pages */
|
||||
@@ -354,22 +373,19 @@ int write_cache_pages(struct vm_file *vmfile, void *buf, unsigned long pfn_start
|
||||
goto copy;
|
||||
|
||||
/*
|
||||
* Page not found, this is a bug.
|
||||
* The page range must have been ready.
|
||||
* Page not found, this is a bug. The writeable page range
|
||||
* must have been readied by read_file_pages()/new_file_pages().
|
||||
*/
|
||||
BUG();
|
||||
|
||||
copy:
|
||||
left = count;
|
||||
|
||||
/* Map the page */
|
||||
page_virtual = l4_map_helper((void *)page_to_phys(head), 1);
|
||||
|
||||
/* Copy the first page and unmap. */
|
||||
copysize = (left < PAGE_SIZE) ? left : PAGE_SIZE;
|
||||
memcpy(page_virtual + cursor_offset, buf, copysize);
|
||||
page_copy(head, task_virt_to_page(task, (unsigned long)buf),
|
||||
cursor_offset, copysize);
|
||||
left -= copysize;
|
||||
l4_unmap_helper(page_virtual, 1);
|
||||
last_offset = head->offset;
|
||||
|
||||
/* Map the rest, copy and unmap. */
|
||||
@@ -381,9 +397,9 @@ copy:
|
||||
BUG_ON(this->offset != last_offset + 1);
|
||||
|
||||
copysize = (left < PAGE_SIZE) ? left : PAGE_SIZE;
|
||||
page_virtual = l4_map_helper((void *)page_to_phys(this), 1);
|
||||
memcpy(page_virtual, buf + count - left, copysize);
|
||||
l4_unmap_helper(page_virtual, 1);
|
||||
page_copy(this, task_virt_to_page(task, (unsigned long)buf +
|
||||
count - left),
|
||||
0, copysize);
|
||||
left -= copysize;
|
||||
last_offset = this->offset;
|
||||
}
|
||||
@@ -392,14 +408,6 @@ copy:
|
||||
return count - left;
|
||||
}
|
||||
|
||||
/*
|
||||
* TODO:
|
||||
* Page in those writeable pages.
|
||||
* Update them,
|
||||
* Then page them out.
|
||||
*
|
||||
* If they're new, fs0 should allocate those pages accordingly.
|
||||
*/
|
||||
int sys_write(l4id_t sender, int fd, void *buf, int count)
|
||||
{
|
||||
unsigned long pfn_wstart, pfn_wend; /* Write start/end */
|
||||
@@ -407,24 +415,36 @@ int sys_write(l4id_t sender, int fd, void *buf, int count)
|
||||
unsigned long pfn_nstart, pfn_nend; /* New pages start/end */
|
||||
unsigned long cursor, byte_offset;
|
||||
struct vm_file *vmfile;
|
||||
struct tcb *t;
|
||||
int err;
|
||||
int err = 0, retval = 0;
|
||||
struct tcb *task;
|
||||
|
||||
BUG_ON(!(t = find_task(sender)));
|
||||
BUG_ON(!(task = find_task(sender)));
|
||||
|
||||
if ((err = check_access(t, buf, count)) < 0) {
|
||||
l4_ipc_return(err);
|
||||
return 0;
|
||||
/* Check fd validity */
|
||||
if (fd < 0 || fd > TASK_FILES_MAX || !task->fd[fd].vmfile) {
|
||||
retval = -EBADF;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* TODO: Check user buffer, count and fd validity */
|
||||
if (fd < 0 || fd > TASK_FILES_MAX) {
|
||||
l4_ipc_return(-EBADF);
|
||||
return 0;
|
||||
/* Check count validity */
|
||||
if (count < 0) {
|
||||
retval = -EINVAL;
|
||||
goto out;
|
||||
} else if (!count) {
|
||||
retval = 0;
|
||||
goto out;
|
||||
}
|
||||
|
||||
vmfile = t->fd[fd].vmfile;
|
||||
cursor = t->fd[fd].cursor;
|
||||
/* Check user buffer validity. */
|
||||
if ((err = validate_task_range(task, (unsigned long)buf,
|
||||
(unsigned long)(buf + count),
|
||||
VM_WRITE | VM_READ)) < 0) {
|
||||
retval = err;
|
||||
goto out;
|
||||
}
|
||||
|
||||
vmfile = task->fd[fd].vmfile;
|
||||
cursor = task->fd[fd].cursor;
|
||||
|
||||
/* See what pages user wants to write */
|
||||
pfn_wstart = __pfn(cursor);
|
||||
@@ -471,14 +491,14 @@ int sys_write(l4id_t sender, int fd, void *buf, int count)
|
||||
* Read in the portion that's already part of the file.
|
||||
*/
|
||||
if ((err = read_file_pages(vmfile, pfn_fstart, pfn_fend)) < 0) {
|
||||
l4_ipc_return(err);
|
||||
return 0;
|
||||
retval = err;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Create new pages for the part that's new in the file */
|
||||
if ((err = new_file_pages(vmfile, pfn_nstart, pfn_nend)) < 0) {
|
||||
l4_ipc_return(err);
|
||||
return 0;
|
||||
retval = err;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -486,10 +506,10 @@ int sys_write(l4id_t sender, int fd, void *buf, int count)
|
||||
* to be written are expected to be in the page cache. Write.
|
||||
*/
|
||||
byte_offset = PAGE_MASK & cursor;
|
||||
if ((err = write_cache_pages(vmfile, buf, pfn_wstart,
|
||||
if ((err = write_cache_pages(vmfile, task, buf, pfn_wstart,
|
||||
pfn_wend, byte_offset, count)) < 0) {
|
||||
l4_ipc_return(err);
|
||||
return 0;
|
||||
retval = err;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -497,7 +517,11 @@ int sys_write(l4id_t sender, int fd, void *buf, int count)
|
||||
* when the file is flushed (e.g. via fflush() or close())
|
||||
*/
|
||||
vmfile->length += count;
|
||||
task->fd[fd].cursor += count;
|
||||
retval = count;
|
||||
|
||||
out:
|
||||
l4_ipc_return(retval);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -23,17 +23,20 @@ int fileio(void)
|
||||
}
|
||||
printf("Created newfile.txt\n");
|
||||
|
||||
printf("%s: write.\n", __TASKNAME__);
|
||||
if ((int)(cnt = write(fd, str, strlen(str))) < 0) {
|
||||
perror("WRITE");
|
||||
return -1;
|
||||
}
|
||||
|
||||
printf("%s: lseek.\n", __TASKNAME__);
|
||||
if ((int)(offset = lseek(fd, 0, SEEK_SET)) < 0) {
|
||||
perror("LSEEK");
|
||||
return -1;
|
||||
}
|
||||
printf("%s: read.\n", __TASKNAME__);
|
||||
if ((int)(cnt = read(fd, buf, strlen(str))) < 0) {
|
||||
perror("WRITE");
|
||||
perror("READ");
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user