From a7ef49da0e07e0a1195794b527fa400c0235fcc7 Mon Sep 17 00:00:00 2001 From: Freya Murphy Date: Tue, 29 Apr 2025 20:59:46 -0400 Subject: tarfs --- kernel/user.c | 36 +++++++++++++++++++++--------------- 1 file changed, 21 insertions(+), 15 deletions(-) (limited to 'kernel/user.c') diff --git a/kernel/user.c b/kernel/user.c index e22248a..4007383 100644 --- a/kernel/user.c +++ b/kernel/user.c @@ -14,13 +14,13 @@ #define USER_STACK_LEN (4 * PAGE_SIZE) #define BLOCK_SIZE (PAGE_SIZE * 1000) -static uint8_t *load_buffer = NULL; +static char *load_buffer = NULL; #define USER_CODE 0x18 #define USER_DATA 0x20 #define RING3 3 -static int user_load_segment(struct pcb *pcb, struct disk *disk, int idx) +static int user_load_segment(struct pcb *pcb, struct file *file, int idx) { Elf64_Phdr hdr; size_t mem_bytes, mem_pages; @@ -56,14 +56,17 @@ static int user_load_segment(struct pcb *pcb, struct disk *disk, int idx) if (mapADDR == NULL) return 1; + // seek to start of segment + if (file->seek(file, hdr.p_offset, SEEK_SET)) + return 1; + // load data size_t total_read = 0; while (total_read < file_bytes) { size_t read = BLOCK_SIZE; if (read > file_bytes - total_read) read = file_bytes - total_read; - if ((read = disk_read(disk, hdr.p_offset + total_read, read, - load_buffer)) < 1) { + if ((read = file->read(file, load_buffer, read)) < 1) { kunmapaddr(mapADDR); return 1; } @@ -79,7 +82,7 @@ static int user_load_segment(struct pcb *pcb, struct disk *disk, int idx) return 0; } -static int user_load_segments(struct pcb *pcb, struct disk *disk) +static int user_load_segments(struct pcb *pcb, struct file *file) { int ret = 0; @@ -91,7 +94,7 @@ static int user_load_segments(struct pcb *pcb, struct disk *disk) return 1; for (int i = 0; i < pcb->n_elf_segments; i++) - if ((ret = user_load_segment(pcb, disk, i))) + if ((ret = user_load_segment(pcb, file, i))) return ret; if (pcb->heap_start == NULL) { @@ -144,11 +147,13 @@ static int validate_elf_hdr(struct pcb *pcb) return 0; } -static int user_load_elf(struct pcb *pcb, struct disk *disk) +static int user_load_elf(struct pcb *pcb, struct file *file) { int ret = 0; - ret = disk_read(disk, 0, sizeof(Elf64_Ehdr), &pcb->elf_header); + if (file->seek(file, 0, SEEK_SET)) + return 1; + ret = file->read(file, (char *)&pcb->elf_header, sizeof(Elf64_Ehdr)); if (ret < 0) return 1; @@ -156,9 +161,10 @@ static int user_load_elf(struct pcb *pcb, struct disk *disk) return 1; pcb->n_elf_segments = pcb->elf_header.e_phnum; - ret = disk_read(disk, pcb->elf_header.e_phoff, - sizeof(Elf64_Phdr) * pcb->elf_header.e_phnum, - &pcb->elf_segments); + if (file->seek(file, pcb->elf_header.e_phoff, SEEK_SET)) + return 1; + ret = file->read(file, (char *)&pcb->elf_segments, + sizeof(Elf64_Phdr) * pcb->elf_header.e_phnum); if (ret < 0) return 1; @@ -199,10 +205,10 @@ static int user_setup_stack(struct pcb *pcb) return 0; } -int user_load(struct pcb *pcb, struct disk *disk) +int user_load(struct pcb *pcb, struct file *file) { // check inputs - if (pcb == NULL || disk == NULL) + if (pcb == NULL || file == NULL) return 1; // allocate memory context @@ -211,11 +217,11 @@ int user_load(struct pcb *pcb, struct disk *disk) goto fail; // load elf information - if (user_load_elf(pcb, disk)) + if (user_load_elf(pcb, file)) goto fail; // load segments into memory - if (user_load_segments(pcb, disk)) + if (user_load_segments(pcb, file)) goto fail; // setup process stack -- cgit v1.2.3-freya From 1a10a3725e7bea67e558715f6e9f78abcb415b3a Mon Sep 17 00:00:00 2001 From: Freya Murphy Date: Wed, 30 Apr 2025 21:07:46 -0400 Subject: finish syscall impls --- kernel/fs/tar.c | 15 ++-- kernel/include/comus/fs.h | 11 ++- kernel/include/comus/limits.h | 4 + kernel/include/comus/procs.h | 4 + kernel/include/comus/syscalls.h | 3 +- kernel/include/comus/user.h | 4 +- kernel/main.c | 5 +- kernel/procs.c | 3 +- kernel/syscall.c | 181 +++++++++++++++++++++++++++++++++++++++- kernel/user.c | 59 +++++++++++-- user/include/stdio.h | 6 +- user/include/sys/types.h | 15 ++++ user/include/unistd.h | 16 ++-- user/init.c | 75 +++++++++++++++++ user/lib/entry.S | 5 +- user/lib/fclose.c | 10 +++ user/lib/fseek.c | 16 ++++ user/lib/syscall.S | 3 + 18 files changed, 398 insertions(+), 37 deletions(-) create mode 100644 user/include/sys/types.h create mode 100644 user/init.c create mode 100644 user/lib/fclose.c create mode 100644 user/lib/fseek.c (limited to 'kernel/user.c') diff --git a/kernel/fs/tar.c b/kernel/fs/tar.c index 7f34107..86af81f 100644 --- a/kernel/fs/tar.c +++ b/kernel/fs/tar.c @@ -150,15 +150,15 @@ int tar_seek(struct file *in, long int off, int whence) switch (whence) { case SEEK_SET: file->offset = off; - return 0; + return file->offset; case SEEK_CUR: file->offset += off; - return 0; + return file->offset; case SEEK_END: file->offset = file->len + off; - return 0; + return file->offset; default: - return 1; + return -1; } } @@ -202,12 +202,17 @@ void tar_close(struct file *file) kfree(file); } -int tar_open(struct file_system *fs, const char *path, struct file **out) +int tar_open(struct file_system *fs, const char *path, int flags, + struct file **out) { struct tar_file *file; struct tar_hdr hdr; size_t sect; + // cannot create or write files + if (flags != O_RDONLY) + return 1; + if (tar_locate(fs, path, &hdr, §, NULL, false)) return 1; diff --git a/kernel/include/comus/fs.h b/kernel/include/comus/fs.h index 2f678b6..044330b 100644 --- a/kernel/include/comus/fs.h +++ b/kernel/include/comus/fs.h @@ -148,6 +148,15 @@ struct file { void (*close)(struct file *file); }; +/// open flags +enum { + O_CREATE = 0x01, + O_RDONLY = 0x02, + O_WRONLY = 0x04, + O_APPEND = 0x08, + O_RDWR = 0x10, +}; + /// file system vtable, used for opening /// and stating files. filesystem mount functions must /// set fs_name, fs_disk, open, and stat. @@ -200,7 +209,7 @@ struct file_system { /// filesystem name const char *fs_name; /// opens a file - int (*open)(struct file_system *fs, const char *fullpath, + int (*open)(struct file_system *fs, const char *fullpath, int flags, struct file **out); /// stats a file int (*stat)(struct file_system *fs, const char *fullpath, diff --git a/kernel/include/comus/limits.h b/kernel/include/comus/limits.h index 4cb348d..1ef13b4 100644 --- a/kernel/include/comus/limits.h +++ b/kernel/include/comus/limits.h @@ -12,6 +12,10 @@ /// max number of processes #define N_PROCS 256 +/// process limits +#define N_OPEN_FILES 64 +#define N_ARGS 64 + /// max nubmer of pci devices #define N_PCI_DEV 256 diff --git a/kernel/include/comus/procs.h b/kernel/include/comus/procs.h index 7b1a70a..3df31c3 100644 --- a/kernel/include/comus/procs.h +++ b/kernel/include/comus/procs.h @@ -13,6 +13,7 @@ #include #include #include +#include #include #include @@ -59,6 +60,9 @@ struct pcb { char *heap_start; size_t heap_len; + // open files + struct file *open_files[N_OPEN_FILES]; + // elf metadata Elf64_Ehdr elf_header; Elf64_Phdr elf_segments[N_ELF_SEGMENTS]; diff --git a/kernel/include/comus/syscalls.h b/kernel/include/comus/syscalls.h index f714184..8b671c2 100644 --- a/kernel/include/comus/syscalls.h +++ b/kernel/include/comus/syscalls.h @@ -30,9 +30,10 @@ #define SYS_poweroff 17 #define SYS_drm 18 #define SYS_ticks 19 +#define SYS_seek 20 // UPDATE THIS DEFINITION IF MORE SYSCALLS ARE ADDED! -#define N_SYSCALLS 20 +#define N_SYSCALLS 21 // interrupt vector entry for system calls #define VEC_SYSCALL 0x80 diff --git a/kernel/include/comus/user.h b/kernel/include/comus/user.h index a1a718b..1b35ac4 100644 --- a/kernel/include/comus/user.h +++ b/kernel/include/comus/user.h @@ -9,13 +9,15 @@ #ifndef USER_H_ #define USER_H_ +#include "comus/memory.h" #include #include /** * Load a user elf program from a file into a pcb */ -int user_load(struct pcb *pcb, struct file *file); +int user_load(struct pcb *pcb, struct file *file, const char **args, + mem_ctx_t args_ctx); /** * Clone a user process. Used for fork(). diff --git a/kernel/main.c b/kernel/main.c index a306e2b..72a6668 100644 --- a/kernel/main.c +++ b/kernel/main.c @@ -26,6 +26,7 @@ void load_init(void) { struct file_system *fs; struct file *file; + const char *init_vector[] = { NULL }; if (pcb_alloc(&init_pcb)) return; @@ -36,10 +37,10 @@ void load_init(void) return; // get init bin - if (fs->open(fs, "bin/apple", &file)) + if (fs->open(fs, "bin/init", O_RDONLY, &file)) return; - if (user_load(init_pcb, file)) { + if (user_load(init_pcb, file, init_vector, kernel_mem_ctx)) { file->close(file); return; } diff --git a/kernel/procs.c b/kernel/procs.c index 9bf7508..d471416 100644 --- a/kernel/procs.c +++ b/kernel/procs.c @@ -1,3 +1,4 @@ +#include "lib/kio.h" #include #include #include @@ -218,7 +219,7 @@ void pcb_zombify(struct pcb *victim) status = (int *)PCB_ARG2(parent); if (pid == 0 || pid == victim->pid) { - PCB_RET(parent) = zchild->pid; + PCB_RET(parent) = victim->pid; assert( pcb_queue_remove(syscall_queue[SYS_waitpid], parent) == SUCCESS, diff --git a/kernel/syscall.c b/kernel/syscall.c index 96d2fcf..44ebfa0 100644 --- a/kernel/syscall.c +++ b/kernel/syscall.c @@ -1,3 +1,5 @@ +#include "comus/fs.h" +#include "lib/kio.h" #include #include #include @@ -23,6 +25,16 @@ static struct pcb *pcb; #define stdout 1 #define stderr 2 +static struct file *get_file_ptr(int fd) +{ + // valid index? + if (fd < 3 || fd >= (N_OPEN_FILES + 3)) + return NULL; + + // will be NULL if not open + return pcb->open_files[fd - 3]; +} + __attribute__((noreturn)) static int sys_exit(void) { ARG1(int, status); @@ -36,6 +48,33 @@ __attribute__((noreturn)) static int sys_exit(void) static int sys_waitpid(void) { + ARG1(pid_t, pid); + ARG2(int *, status); + + struct pcb *child; + for (int i = 0; i < N_PROCS; i++) { + child = &ptable[i]; + if (child->state != PROC_STATE_ZOMBIE) + continue; + if (child->parent != pcb) + continue; + + // we found a child! + if (pid && pid != child->pid) + continue; + + // set status + mem_ctx_switch(pcb->memctx); + *status = child->exit_status; + mem_ctx_switch(kernel_mem_ctx); + + // clean up child process + pcb_cleanup(child); + + // return + return child->pid; + } + // arguments are read later // by procs.c pcb->state = PROC_STATE_BLOCKED; @@ -60,6 +99,125 @@ static int sys_fork(void) return 0; } +static int sys_exec(void) +{ + ARG1(const char *, in_filename); + ARG2(const char **, in_args); + + struct file_system *fs; + struct file *file; + char filename[N_FILE_NAME]; + struct pcb save; + + // save data + file = NULL; + save = *pcb; + + // read filename + mem_ctx_switch(pcb->memctx); + memcpy(filename, in_filename, strlen(in_filename) + 1); + mem_ctx_switch(kernel_mem_ctx); + + // get binary + fs = fs_get_root_file_system(); + if (fs == NULL) + goto fail; + if (fs->open(fs, filename, O_RDONLY, &file)) + goto fail; + + // load program + save = *pcb; + if (user_load(pcb, file, in_args, save.memctx)) + goto fail; + file->close(file); + mem_ctx_free(save.memctx); + schedule(pcb); + dispatch(); + +fail: + *pcb = save; + if (file) + file->close(file); + return 1; +} + +static int sys_open(void) +{ + ARG1(const char *, in_filename); + ARG2(int, flags); + + char filename[N_FILE_NAME]; + struct file_system *fs; + struct file **file; + int fd; + + // read filename + mem_ctx_switch(pcb->memctx); + memcpy(filename, in_filename, strlen(in_filename)); + mem_ctx_switch(kernel_mem_ctx); + + // get fd + for (fd = 3; fd < (N_OPEN_FILES + 3); fd++) { + if (pcb->open_files[fd - 3] == NULL) { + file = &pcb->open_files[fd - 3]; + break; + } + } + + // could not find fd + if (fd == (N_OPEN_FILES + 3)) + return -1; + + // open file + fs = fs_get_root_file_system(); + if (fs == NULL) + return -1; + if (fs->open(fs, filename, flags, file)) + return -1; + + // file opened + return fd; +} + +static int sys_close(void) +{ + ARG1(int, fd); + + struct file *file; + file = get_file_ptr(fd); + if (file == NULL) + return 1; + + file->close(file); + return 0; +} + +static int sys_read(void) +{ + ARG1(int, fd); + ARG2(void *, buffer); + ARG3(size_t, nbytes); + + struct file *file; + char *map_buf; + + map_buf = kmapuseraddr(pcb->memctx, buffer, nbytes); + if (map_buf == NULL) + return -1; + + file = get_file_ptr(fd); + if (file == NULL) + goto fail; + + nbytes = file->read(file, map_buf, nbytes); + kunmapaddr(map_buf); + return nbytes; + +fail: + kunmapaddr(map_buf); + return -1; +} + static int sys_write(void) { ARG1(int, fd); @@ -324,17 +482,34 @@ static int sys_ticks(void) return 0; } +static int sys_seek(void) +{ + RET(long int, ret); + ARG1(int, fd); + ARG2(long int, off); + ARG3(int, whence); + + struct file *file; + file = get_file_ptr(fd); + if (file == NULL) + return -1; + + *ret = file->seek(file, off, whence); + return 0; +} + static int (*syscall_tbl[N_SYSCALLS])(void) = { [SYS_exit] = sys_exit, [SYS_waitpid] = sys_waitpid, - [SYS_fork] = sys_fork, [SYS_exec] = NULL, - [SYS_open] = NULL, [SYS_close] = NULL, - [SYS_read] = NULL, [SYS_write] = sys_write, + [SYS_fork] = sys_fork, [SYS_exec] = sys_exec, + [SYS_open] = sys_open, [SYS_close] = sys_close, + [SYS_read] = sys_read, [SYS_write] = sys_write, [SYS_getpid] = sys_getpid, [SYS_getppid] = sys_getppid, [SYS_gettime] = sys_gettime, [SYS_getprio] = sys_getprio, [SYS_setprio] = sys_setprio, [SYS_kill] = sys_kill, [SYS_sleep] = sys_sleep, [SYS_brk] = sys_brk, [SYS_sbrk] = sys_sbrk, [SYS_poweroff] = sys_poweroff, [SYS_drm] = sys_drm, [SYS_ticks] = sys_ticks, + [SYS_seek] = sys_seek, }; void syscall_handler(void) diff --git a/kernel/user.c b/kernel/user.c index 4007383..9612710 100644 --- a/kernel/user.c +++ b/kernel/user.c @@ -57,7 +57,7 @@ static int user_load_segment(struct pcb *pcb, struct file *file, int idx) return 1; // seek to start of segment - if (file->seek(file, hdr.p_offset, SEEK_SET)) + if (file->seek(file, hdr.p_offset, SEEK_SET) < 0) return 1; // load data @@ -151,7 +151,7 @@ static int user_load_elf(struct pcb *pcb, struct file *file) { int ret = 0; - if (file->seek(file, 0, SEEK_SET)) + if (file->seek(file, 0, SEEK_SET) < 0) return 1; ret = file->read(file, (char *)&pcb->elf_header, sizeof(Elf64_Ehdr)); if (ret < 0) @@ -161,7 +161,7 @@ static int user_load_elf(struct pcb *pcb, struct file *file) return 1; pcb->n_elf_segments = pcb->elf_header.e_phnum; - if (file->seek(file, pcb->elf_header.e_phoff, SEEK_SET)) + if (file->seek(file, pcb->elf_header.e_phoff, SEEK_SET) < 0) return 1; ret = file->read(file, (char *)&pcb->elf_segments, sizeof(Elf64_Phdr) * pcb->elf_header.e_phnum); @@ -171,14 +171,56 @@ static int user_load_elf(struct pcb *pcb, struct file *file) return 0; } -static int user_setup_stack(struct pcb *pcb) +static int user_setup_stack(struct pcb *pcb, const char **args, + mem_ctx_t args_ctx) { - // allocate stack + /* args */ + int argbytes = 0; + int argc = 0; + + mem_ctx_switch(args_ctx); + + while (args[argc] != NULL) { + int n = strlen(args[argc]) + 1; + if ((argbytes + n) > USER_STACK_LEN) { + // oops - ignore this and any others + break; + } + argbytes += n; + argc++; + } + + // round to nearest multiple of 8 + argbytes = (argbytes + 7) & 0xfffffffffffffff8; + + // allocate arg strings on kernel stack + char argstrings[argbytes]; + char *argv[argc + 1]; + memset(argstrings, 0, sizeof(argstrings)); + memset(argv, 0, sizeof(argv)); + + // Next, duplicate the argument strings, and create pointers to + // each one in our argv. + char *tmp = argstrings; + for (int i = 0; i < argc; ++i) { + int nb = strlen(args[i]) + 1; + strcpy(tmp, args[i]); + argv[i] = tmp; + tmp += nb; + } + + // trailing NULL pointer + argv[argc] = NULL; + + mem_ctx_switch(kernel_mem_ctx); + + /* stack */ if (mem_alloc_pages_at(pcb->memctx, USER_STACK_LEN / PAGE_SIZE, (void *)(USER_STACK_TOP - USER_STACK_LEN), F_WRITEABLE | F_UNPRIVILEGED) == NULL) return 1; + /* regs */ memset(&pcb->regs, 0, sizeof(struct cpu_regs)); // pgdir @@ -189,7 +231,7 @@ static int user_setup_stack(struct pcb *pcb) pcb->regs.es = USER_DATA | RING3; pcb->regs.ds = USER_DATA | RING3; // registers - pcb->regs.rdi = 0; // argc + pcb->regs.rdi = argc; // argc pcb->regs.rsi = 0; // argv // intruction pointer pcb->regs.rip = pcb->elf_header.e_entry; @@ -205,7 +247,8 @@ static int user_setup_stack(struct pcb *pcb) return 0; } -int user_load(struct pcb *pcb, struct file *file) +int user_load(struct pcb *pcb, struct file *file, const char **args, + mem_ctx_t args_ctx) { // check inputs if (pcb == NULL || file == NULL) @@ -225,7 +268,7 @@ int user_load(struct pcb *pcb, struct file *file) goto fail; // setup process stack - if (user_setup_stack(pcb)) + if (user_setup_stack(pcb, args, args_ctx)) goto fail; // success diff --git a/user/include/stdio.h b/user/include/stdio.h index fe29c9d..bb57c6d 100644 --- a/user/include/stdio.h +++ b/user/include/stdio.h @@ -252,7 +252,7 @@ extern size_t fwrite(const void *restrict ptr, size_t size, size_t n, * @param stream - the stream to seek * @param off - the offset from whence * @param whence - where to seek from (SEEK_SET, SEEK_CUR, SEEK_END) - * @returns 0 on success, -1 on error setting errno + * @returns new offset on success, -1 on error */ extern int fseek(FILE *stream, long int off, int whence); @@ -260,9 +260,9 @@ extern int fseek(FILE *stream, long int off, int whence); * return the current position of stream * * @param stream - the stream to tell - * @return the position on success, -1 on error setting errno + * @returns new offset on success, -1 on error */ -extern long int ftell(FILE *stream); +extern long ftell(FILE *stream); /** * rewing to the begining of a stream diff --git a/user/include/sys/types.h b/user/include/sys/types.h new file mode 100644 index 0000000..f1b3266 --- /dev/null +++ b/user/include/sys/types.h @@ -0,0 +1,15 @@ +/** + * @file types.h + * + * @author Freya Murphy + * + * System types + */ + +#ifndef _TYPES_H +#define _TYPES_H + +typedef long int off_t; +typedef unsigned short pid_t; + +#endif /* types.h */ diff --git a/user/include/unistd.h b/user/include/unistd.h index cad3a81..4f582d2 100644 --- a/user/include/unistd.h +++ b/user/include/unistd.h @@ -11,11 +11,10 @@ #include #include +#include /* System Call Definitions */ -typedef unsigned short pid_t; - enum { S_SET = 0, S_CUR = 1, @@ -27,7 +26,7 @@ enum { O_RDONLY = 0x02, O_WRONLY = 0x04, O_APPEND = 0x08, - O_RDWR = O_RDONLY | O_WRONLY, + O_RDWR = 0x010, }; /** @@ -67,11 +66,9 @@ extern int fork(void); * * @param prog - program table index of the program to exec * @param args - the command-line argument vector - * - * Does not return if it succeeds; if it returns, something has - * gone wrong. + * @returns error code on failure */ -extern void exec(const char *filename, char **args); +extern int exec(const char *filename, const char **args); /** * open a stream with a given filename @@ -85,8 +82,9 @@ extern int open(const char *filename, int flags); * closes a stream with the given file descriptior * * @param fd - the file descriptior of the open stream + * @returns 0 on success, error code on invalid fd */ -extern void close(int fd); +extern int close(int fd); /** * read into a buffer from a stream @@ -116,7 +114,7 @@ extern int write(int fd, const void *buffer, size_t nbytes); * @param whence - whence to seek * @return 0 on success, or an error code */ -extern int seek(int fd, long int off, int whence); +extern off_t seek(int fd, off_t off, int whence); /** * gets the pid of the calling process diff --git a/user/init.c b/user/init.c new file mode 100644 index 0000000..18e70a2 --- /dev/null +++ b/user/init.c @@ -0,0 +1,75 @@ +#include +#include + +#define MAX_ARGS 4 + +struct proc { + pid_t pid; + const char *filename; + const char *args[MAX_ARGS]; +}; + +static struct proc spawn_table[] = { + // apple + { 0, "bin/apple", { NULL } }, + // end, + { 0, NULL, { NULL } }, +}; + +static int spawn(const char *filename, const char **args) +{ + int ret; + + // fork init + if ((ret = fork()) != 0) + return ret; + + // call exec + if ((ret = exec(filename, args))) + exit(ret); + + // should not happen! + exit(1); +} + +int main(void) +{ + struct proc *proc; + + // spawn our processes + for (proc = spawn_table; proc->filename != NULL; proc++) { + int pid; + pid = spawn(proc->filename, proc->args); + if (pid < 0) + fprintf(stderr, "init: cannot exec '%s': %d\n", proc->filename, + pid); + proc->pid = pid; + } + + // clean up dead on restart ours + while (1) { + int pid, status; + + pid = waitpid(0, &status); + if (pid < 0) + continue; + + printf("init: pid %d exited with %d\n", pid, status); + + // figure out if this is one of ours + for (proc = spawn_table; proc->filename != NULL; proc++) { + if (proc->pid == pid) { + proc->pid = 0; + pid = spawn(proc->filename, proc->args); + if (pid < 0) + fprintf(stderr, "init: cannot exec '%s': %d\n", + proc->filename, pid); + proc->pid = pid; + break; + } + } + } + + // very very bad! + return 1; +} diff --git a/user/lib/entry.S b/user/lib/entry.S index 40570b5..efaa652 100644 --- a/user/lib/entry.S +++ b/user/lib/entry.S @@ -5,7 +5,6 @@ .section .text .code64 _start: - call main - subq $16, %rsp # ??? - pushq %rax + call main + movq %rax, %rdi call exit diff --git a/user/lib/fclose.c b/user/lib/fclose.c new file mode 100644 index 0000000..be31421 --- /dev/null +++ b/user/lib/fclose.c @@ -0,0 +1,10 @@ +#include +#include + +void fclose(FILE *stream) +{ + int fd; + + fd = (uintptr_t)stream; + close(fd); +} diff --git a/user/lib/fseek.c b/user/lib/fseek.c new file mode 100644 index 0000000..a7a3377 --- /dev/null +++ b/user/lib/fseek.c @@ -0,0 +1,16 @@ +#include +#include + +int fseek(FILE *stream, long off, int whence) +{ + int fd; + fd = (uintptr_t)stream; + return seek(fd, off, whence); +} + +long ftell(FILE *stream) +{ + int fd; + fd = (uintptr_t)stream; + return seek(fd, 0, SEEK_CUR); +} diff --git a/user/lib/syscall.S b/user/lib/syscall.S index 2ba4dc0..9f7025e 100644 --- a/user/lib/syscall.S +++ b/user/lib/syscall.S @@ -13,6 +13,8 @@ SYSCALL exit SYS_exit SYSCALL waitpid SYS_waitpid SYSCALL fork SYS_fork SYSCALL exec SYS_exec +SYSCALL open SYS_open +SYSCALL close SYS_close SYSCALL read SYS_read SYSCALL write SYS_write SYSCALL getpid SYS_getpid @@ -27,3 +29,4 @@ SYSCALL sbrk SYS_sbrk SYSCALL poweroff SYS_poweroff SYSCALL drm SYS_drm SYSCALL ticks SYS_ticks +SYSCALL seek SYS_seek -- cgit v1.2.3-freya From b54fdd17a99a7feffc36a3ad067d4293ba3e9577 Mon Sep 17 00:00:00 2001 From: Freya Murphy Date: Tue, 6 May 2025 12:36:04 -0400 Subject: add some memory logging --- kernel/memory/paging.c | 46 ++++++++++++++++++++++++++----------- kernel/user.c | 62 ++++++++++++++++++++++++++++++++++---------------- 2 files changed, 76 insertions(+), 32 deletions(-) (limited to 'kernel/user.c') diff --git a/kernel/memory/paging.c b/kernel/memory/paging.c index e21fd34..fc3b256 100644 --- a/kernel/memory/paging.c +++ b/kernel/memory/paging.c @@ -1,4 +1,3 @@ -#include "lib/kio.h" #include #include @@ -6,7 +5,6 @@ #include "physalloc.h" #include "paging.h" #include "memory.h" -#include // PAGE MAP LEVEL 4 ENTRY struct pml4e { @@ -259,8 +257,10 @@ static volatile struct pml4 *pml4_alloc(void) volatile struct pml4 *pPML4, *vPML4; pPML4 = alloc_phys_page(); - if (pPML4 == NULL) + if (pPML4 == NULL) { + ERROR("Could not allocate PML4"); return NULL; + } vPML4 = PML4_MAP(pPML4); memsetv(vPML4, 0, sizeof(struct pml4)); @@ -288,8 +288,10 @@ static volatile struct pdpt *pdpt_alloc(volatile struct pml4 *pPML4, } pPDPT = alloc_phys_page(); - if (pPML4 == NULL) + if (pPDPT == NULL) { + ERROR("Could not allocate PDPT"); return NULL; + } vPDPT = PDPT_MAP(pPDPT); memsetv(vPDPT, 0, sizeof(struct pdpt)); @@ -321,8 +323,10 @@ static volatile struct pd *pd_alloc(volatile struct pdpt *pPDPT, void *vADDR, } pPD = alloc_phys_page(); - if (pPDPT == NULL) + if (pPD == NULL) { + ERROR("Could not allocate PD"); return NULL; + } vPD = PD_MAP(pPD); memsetv(vPD, 0, sizeof(struct pd)); @@ -354,8 +358,10 @@ static volatile struct pt *pt_alloc(volatile struct pd *pPD, void *vADDR, } pPT = alloc_phys_page(); - if (pPT == NULL) + if (pPT == NULL) { + ERROR("Could not allocate PT"); return NULL; + } vPT = PT_MAP(pPT); memsetv(vPT, 0, sizeof(struct pt)); @@ -911,11 +917,15 @@ void *mem_mapaddr(mem_ctx_t ctx, void *phys, void *virt, size_t len, // get page aligned (or allocate) vitural address if (virt == NULL) virt = virtaddr_alloc(&ctx->virtctx, pages); - if (virt == NULL) + if (virt == NULL) { + ERROR("Could not alloc vitural address for %zu pages", pages); return NULL; + } - if (virtaddr_take(&ctx->virtctx, virt, pages)) + if (virtaddr_take(&ctx->virtctx, virt, pages)) { + ERROR("Could not take vitural address: %p", virt); return NULL; + } assert((uint64_t)virt % PAGE_SIZE == 0, "mem_mapaddr: vitural address not page aligned"); @@ -923,6 +933,7 @@ void *mem_mapaddr(mem_ctx_t ctx, void *phys, void *virt, size_t len, if (map_pages((volatile struct pml4 *)ctx->pml4, virt, aligned_phys, F_PRESENT | flags, pages)) { virtaddr_free(&ctx->virtctx, virt); + ERROR("Could not map pages"); return NULL; } @@ -1028,21 +1039,30 @@ void *mem_alloc_pages_at(mem_ctx_t ctx, size_t count, void *virt, { void *phys = NULL; - if (virtaddr_take(&ctx->virtctx, virt, count)) + if (virtaddr_take(&ctx->virtctx, virt, count)) { + ERROR("Could not take vitural address: %p", virt); return NULL; + } phys = alloc_phys_pages_exact(count); - if (phys == NULL) - return NULL; + if (phys == NULL) { + ERROR("Could not allocate %zu physical pages", count); + goto fail; + } if (map_pages((volatile struct pml4 *)ctx->pml4, virt, phys, flags, count)) { - free_phys_pages(phys, count); - return NULL; + ERROR("Could not map pages"); + goto fail; } return virt; +fail: + free_phys_pages(phys, count); + virtaddr_free(&ctx->virtctx, virt); + return NULL; + // size_t pages_needed = count; // // struct phys_page_slice prev_phys_block = PHYS_PAGE_SLICE_NULL; diff --git a/kernel/user.c b/kernel/user.c index 9612710..97d8f0f 100644 --- a/kernel/user.c +++ b/kernel/user.c @@ -1,3 +1,4 @@ +#include "lib/kio.h" #include #include #include @@ -14,7 +15,7 @@ #define USER_STACK_LEN (4 * PAGE_SIZE) #define BLOCK_SIZE (PAGE_SIZE * 1000) -static char *load_buffer = NULL; +static uint8_t *load_buffer = NULL; #define USER_CODE 0x18 #define USER_DATA 0x20 @@ -49,16 +50,22 @@ static int user_load_segment(struct pcb *pcb, struct file *file, int idx) // allocate memory in user process if (mem_alloc_pages_at(pcb->memctx, mem_pages, (void *)hdr.p_vaddr, - F_WRITEABLE | F_UNPRIVILEGED) == NULL) + F_WRITEABLE | F_UNPRIVILEGED) == NULL) { + ERROR("Could not allocate memory for elf segment"); return 1; + } mapADDR = kmapuseraddr(pcb->memctx, (void *)hdr.p_vaddr, mem_bytes); - if (mapADDR == NULL) + if (mapADDR == NULL) { + ERROR("Could load memory for elf segment"); return 1; + } // seek to start of segment - if (file->seek(file, hdr.p_offset, SEEK_SET) < 0) + if (file->seek(file, hdr.p_offset, SEEK_SET) < 0) { + ERROR("Could not load elf segment"); return 1; + } // load data size_t total_read = 0; @@ -66,11 +73,13 @@ static int user_load_segment(struct pcb *pcb, struct file *file, int idx) size_t read = BLOCK_SIZE; if (read > file_bytes - total_read) read = file_bytes - total_read; + TRACE("Reading %zu bytes...", read); if ((read = file->read(file, load_buffer, read)) < 1) { kunmapaddr(mapADDR); + ERROR("Could not load elf segment"); return 1; } - memcpy(mapADDR + total_read, load_buffer, read); + memcpyv(mapADDR + total_read, load_buffer, read); total_read += read; } @@ -89,10 +98,15 @@ static int user_load_segments(struct pcb *pcb, struct file *file) pcb->heap_start = NULL; pcb->heap_len = 0; - if (load_buffer == NULL) - if ((load_buffer = kalloc(BLOCK_SIZE)) == NULL) + if (load_buffer == NULL) { + load_buffer = kalloc(BLOCK_SIZE); + if (load_buffer == NULL) { + ERROR("Could not allocate user load buffer"); return 1; + } + } + TRACE("Loading %u elf segments", pcb->n_elf_segments); for (int i = 0; i < pcb->n_elf_segments; i++) if ((ret = user_load_segment(pcb, file, i))) return ret; @@ -110,12 +124,12 @@ static int validate_elf_hdr(struct pcb *pcb) Elf64_Ehdr *ehdr = &pcb->elf_header; if (strncmp((const char *)ehdr->e_ident, ELFMAG, SELFMAG)) { - WARN("Invalid ELF File."); + ERROR("Invalid ELF File."); return 1; } if (ehdr->e_ident[EI_CLASS] != ELFCLASS64) { - WARN("Unsupported ELF Class."); + ERROR("Unsupported ELF Class."); return 1; } @@ -125,17 +139,17 @@ static int validate_elf_hdr(struct pcb *pcb) } if (ehdr->e_machine != EM_X86_64) { - WARN("Unsupported ELF File target."); + ERROR("Unsupported ELF File target."); return 1; } if (ehdr->e_ident[EI_VERSION] != EV_CURRENT) { - WARN("Unsupported ELF File version."); + ERROR("Unsupported ELF File version."); return 1; } if (ehdr->e_phnum > N_ELF_SEGMENTS) { - WARN("Too many ELF segments."); + ERROR("Too many ELF segments."); return 1; } @@ -151,22 +165,30 @@ static int user_load_elf(struct pcb *pcb, struct file *file) { int ret = 0; - if (file->seek(file, 0, SEEK_SET) < 0) + if (file->seek(file, 0, SEEK_SET) < 0) { + ERROR("Cannot read ELF header."); return 1; - ret = file->read(file, (char *)&pcb->elf_header, sizeof(Elf64_Ehdr)); - if (ret < 0) + } + ret = file->read(file, &pcb->elf_header, sizeof(Elf64_Ehdr)); + if (ret < 0) { + ERROR("Cannot read ELF header."); return 1; + } if (validate_elf_hdr(pcb)) return 1; pcb->n_elf_segments = pcb->elf_header.e_phnum; - if (file->seek(file, pcb->elf_header.e_phoff, SEEK_SET) < 0) + if (file->seek(file, pcb->elf_header.e_phoff, SEEK_SET) < 0) { + ERROR("Cannot read ELF segemts"); return 1; - ret = file->read(file, (char *)&pcb->elf_segments, + } + ret = file->read(file, &pcb->elf_segments, sizeof(Elf64_Phdr) * pcb->elf_header.e_phnum); - if (ret < 0) + if (ret < 0) { + ERROR("Cannot read ELF segemts"); return 1; + } return 0; } @@ -217,8 +239,10 @@ static int user_setup_stack(struct pcb *pcb, const char **args, /* stack */ if (mem_alloc_pages_at(pcb->memctx, USER_STACK_LEN / PAGE_SIZE, (void *)(USER_STACK_TOP - USER_STACK_LEN), - F_WRITEABLE | F_UNPRIVILEGED) == NULL) + F_WRITEABLE | F_UNPRIVILEGED) == NULL) { + ERROR("Could not allocate user stack"); return 1; + } /* regs */ memset(&pcb->regs, 0, sizeof(struct cpu_regs)); -- cgit v1.2.3-freya From f14e707144e805611ea01a8f2fd7f1e1beeb65c1 Mon Sep 17 00:00:00 2001 From: Freya Murphy Date: Tue, 6 May 2025 13:21:53 -0400 Subject: fixes --- config/grub.cfg | 3 +-- kernel/user.c | 1 + 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'kernel/user.c') diff --git a/config/grub.cfg b/config/grub.cfg index 82c5db7..13c5167 100644 --- a/config/grub.cfg +++ b/config/grub.cfg @@ -1,9 +1,8 @@ set timeout=1 set default=0 insmod all_video -insmod normal menuentry "kern" { multiboot2 /boot/kernel - # module2 /boot/initrd.tar + module2 /boot/initrd.tar } diff --git a/kernel/user.c b/kernel/user.c index 97d8f0f..27b46df 100644 --- a/kernel/user.c +++ b/kernel/user.c @@ -79,6 +79,7 @@ static int user_load_segment(struct pcb *pcb, struct file *file, int idx) ERROR("Could not load elf segment"); return 1; } + TRACE("Read %zu bytes", read); memcpyv(mapADDR + total_read, load_buffer, read); total_read += read; } -- cgit v1.2.3-freya