diff --git a/Makefile b/Makefile index e47e9942..993aa303 100644 --- a/Makefile +++ b/Makefile @@ -72,7 +72,6 @@ dump: $(ARCH)objdump -S -D kernel.elf > dump $(MAKE) -C user $@ $(MAKE) -C tools $@ - $(MAKE) -C modules $@ install: $(MAKE) clean diff --git a/kernel/exceptions/irq.c b/kernel/exceptions/irq.c index 8f4dd08f..26467229 100644 --- a/kernel/exceptions/irq.c +++ b/kernel/exceptions/irq.c @@ -107,7 +107,7 @@ void irq_el1_handler() { if (irq == IRQ_TIMER) { bool can_preempt = true; - if (get_current_proc() && get_current_proc()->mm.ttbr0 && (get_current_proc()->spsr & 0xF) != 0) can_preempt = false; + if (get_current_proc() && get_current_proc()->mm.ttbr0 && is_privileged(get_current_proc())) can_preempt = false; if (RPI_BOARD != 3) write32(GICC_BASE + 0x10, irq); syscall_depth--; if (can_preempt) switch_proc(INTERRUPT); diff --git a/kernel/exceptions/timer.c b/kernel/exceptions/timer.c index a7582880..ca996028 100644 --- a/kernel/exceptions/timer.c +++ b/kernel/exceptions/timer.c @@ -83,7 +83,7 @@ uint64_t timer_now() { asm volatile ("mrs %0, cntvct_el0" : "=r"(val)); return val; } - +//TODO: do we want more precision since we have it? uint64_t timer_now_msec() { uint64_t ticks = timer_now(); uint64_t freq = rd_cntfrq_el0(); diff --git a/kernel/filesystem/disk.h b/kernel/filesystem/disk.h index 3d4748ff..5fe9584d 100644 --- a/kernel/filesystem/disk.h +++ b/kernel/filesystem/disk.h @@ -7,7 +7,7 @@ extern "C" { #include "types.h" #include "files/system_module.h" -bool init_disk_device(); +bool init_disk_device(system_module *mod); void disk_verbose(); void disk_write(const void *buffer, uint32_t sector, uint32_t count); diff --git a/kernel/filesystem/fat32.cpp b/kernel/filesystem/fat32.cpp index 70ad4d6b..3ce9a314 100644 --- a/kernel/filesystem/fat32.cpp +++ b/kernel/filesystem/fat32.cpp @@ -114,7 +114,7 @@ bool FAT32FS::write_section_to_cluster(u32 cluster, u32 offset, void *buf, size_ u32 sector_count = ceil(((float)offset + size)/512); - void *initial = zalloc(512 * sector_count); + void *initial = kalloc(fs_page, 512 * sector_count, ALIGN_64B, MEM_PRIV_KERNEL); disk_read(initial, sector, sector_count); @@ -505,8 +505,9 @@ size_t FAT32FS::write_file(file *descriptor, const char* buf, size_t size){ if (written) write_to_disk(mfile->serial, mfile->file_buffer.buffer, mfile->file_buffer.buffer_size); - - truncate(descriptor, mfile->file_size); + + descriptor->size = mfile->file_size; + truncate(descriptor); return written; } @@ -625,7 +626,7 @@ bool FAT32FS::stat(const char *path, fs_stat *out_stat){ return true; } -bool FAT32FS::truncate(file *descriptor, size_t size){ +bool FAT32FS::truncate(file *descriptor){ irq_flags_t irq = irq_save_disable(); module_file *mfile = (module_file*)hash_map_get(open_files, &descriptor->id, sizeof(uint64_t)); if (!mfile || !mfile->name.data) { @@ -639,7 +640,7 @@ bool FAT32FS::truncate(file *descriptor, size_t size){ if (!result.found) return false; - result.entry.filesize = size & UINT32_MAX; + result.entry.filesize = descriptor->size & UINT32_MAX; write_section_to_cluster(result.cluster,result.offset, &result.entry, sizeof(f32file_entry)); @@ -684,14 +685,15 @@ bool boot_stat(const char *path, fs_stat *out_stat){ return fs_driver->stat(path, out_stat); } -bool boot_truncate(file *descriptor, size_t size){ - return fs_driver->truncate(descriptor, size); +bool boot_truncate(file *descriptor){ + return fs_driver->truncate(descriptor); } system_module boot_fs_module = (system_module){ .name = "boot", .mount = "boot", .version = VERSION_NUM(0, 1, 0, 0), + .owner = 0, .init = boot_partition_init, .fini = boot_partition_fini, .open = boot_partition_open, diff --git a/kernel/filesystem/fat32.hpp b/kernel/filesystem/fat32.hpp index ee134e28..0d7de401 100644 --- a/kernel/filesystem/fat32.hpp +++ b/kernel/filesystem/fat32.hpp @@ -95,7 +95,7 @@ class FAT32FS: public FSDriver { size_t list_contents(const char *path, void* buf, size_t size, uint64_t *offset) override; void close_file(file* descriptor) override; bool stat(const char *path, fs_stat *out_stat) override; - bool truncate(file *descriptor, size_t size) override; + bool truncate(file *descriptor) override; protected: sizedptr read_full_file(uint32_t cluster_start, uint32_t cluster_size, uint32_t cluster_count, uint64_t file_size, uint32_t root_index); void read_FAT(uint32_t location, uint32_t size, uint8_t count); diff --git a/kernel/filesystem/filesystem.c b/kernel/filesystem/filesystem.c index f8e4157c..e15488b1 100644 --- a/kernel/filesystem/filesystem.c +++ b/kernel/filesystem/filesystem.c @@ -6,6 +6,7 @@ #include "process/scheduler.h" #include "pipe.h" #include "files/dir_list.h" +#include "process/jobs/job_manager.h" uint64_t fd_id = 256;//First byte reserved @@ -46,25 +47,31 @@ bool init_filesystem(){ return true; } -FS_RESULT open_file_global(module_root *root, const char* path, file* descriptor, system_module **mod){ +FS_RESULT open_file_global(module_root *root, const char* path, file* descriptor, system_module **out_mod){ const char *search_path = path; if (*search_path == '/') search_path++; if (!*search_path) return FS_RESULT_NOTFOUND; - system_module *module = get_module_from(root, &search_path); - if (!module) return FS_RESULT_NOTFOUND; - if (!module->open) return FS_RESULT_NOTFOUND; - FS_RESULT result = module->open(search_path, descriptor); + system_module *mod = get_module_from(root, &search_path); + if (!mod) return FS_RESULT_NOTFOUND; + if (!mod->open) return FS_RESULT_NOTFOUND; + FS_RESULT result = FS_RESULT_DRIVER_ERROR; + if (mod->owner != get_kernel_proc()->id){ + job_make(job_open, mod, { + job_serialize_str(&app, 0, search_path); + job_serialize_fd(&app, 1, descriptor, copy_on_end); + }); + return j_ret; + } else { + result = mod->open(search_path, descriptor); + } if (result != FS_RESULT_SUCCESS) return result; if (!open_files) return FS_RESULT_DRIVER_ERROR; descriptor->cursor = 0; - *mod = module; + *out_mod = mod; return FS_RESULT_SUCCESS; } -FS_RESULT open_file(module_root *root, const char* path, file* descriptor){ - system_module *mod = 0; - FS_RESULT result = open_file_global(root, path, descriptor, &mod); - if (result != FS_RESULT_SUCCESS) return result; +FS_RESULT instance_local_fd(system_module *mod, file *descriptor){ open_file_descriptors *of = (open_file_descriptors*)open_files_alloc(sizeof(open_file_descriptors)); if (!of) { close_file_global(descriptor, mod); @@ -76,9 +83,7 @@ FS_RESULT open_file(module_root *root, const char* path, file* descriptor){ of->mod = mod; of->pid = get_current_proc_pid(); descriptor->id = of->file_id; - irq_flags_t irq = irq_save_disable(); int put = hash_map_put(open_files, &of->file_id, sizeof(uint64_t), of); - irq_restore(irq); if (put != 1) { file tmp = { @@ -90,9 +95,19 @@ FS_RESULT open_file(module_root *root, const char* path, file* descriptor){ release(of); return FS_RESULT_DRIVER_ERROR; } + return FS_RESULT_SUCCESS; } +FS_RESULT open_file(module_root *root, const char* path, file* descriptor){ + system_module *mod = 0; + FS_RESULT result = open_file_global(root, path, descriptor, &mod); + if (result != FS_RESULT_SUCCESS) return result; + result = instance_local_fd(mod, descriptor); + if (result != FS_RESULT_SUCCESS) return result; + return result; +} + size_t read_file(file *descriptor, char* buf, size_t size){ if (!open_files){ kprintf("[FS] No open files"); @@ -111,7 +126,16 @@ size_t read_file(file *descriptor, char* buf, size_t size){ .cursor = start_cursor, .data_type = descriptor->data_type }; - size_t amount_read = local.mod->read(&gfd, buf, size, start_cursor); + size_t amount_read = 0; + if (local.mod->owner != get_kernel_proc()->id){ + job_make(job_read, local.mod, { + job_serialize_fd(&app, 0, &gfd, copy_on_start); + job_serialize_buf(&app, 1, true, (void*)buf, size, copy_on_end); + }); + return j_ret; + } else { + amount_read = local.mod->read(&gfd, buf, size, start_cursor); + } descriptor->cursor = gfd.cursor != start_cursor ? gfd.cursor : start_cursor + amount_read; descriptor->size = gfd.size; return amount_read; @@ -136,7 +160,13 @@ void close_file(file *descriptor){ void close_file_global(file *descriptor, system_module *mod){ if (!mod || !mod->close) return; - mod->close(descriptor); + if (mod->owner != get_kernel_proc()->id){ + job_make(job_close, mod, { + job_serialize_fd(&app, 0, descriptor, copy_on_start); + }); + return; + } else + mod->close(descriptor); } size_t write_file(file *descriptor, const char* buf, size_t size){ @@ -162,7 +192,16 @@ size_t write_file(file *descriptor, const char* buf, size_t size){ .cursor = start_cursor, .data_type = descriptor->data_type }; - size_t amount_written = local.mod->write(&gfd, buf, size, 0); + size_t amount_written = 0; + if (local.mod->owner != get_kernel_proc()->id){ + job_make(job_write, local.mod, { + job_serialize_fd(&app, 0, &gfd, copy_on_start); + job_serialize_buf(&app, 1, true, (void*)buf, size, copy_on_start); + }); + return j_ret; + } else { + amount_written = local.mod->write(&gfd, buf, size, 0); + } descriptor->cursor = gfd.cursor != start_cursor ? gfd.cursor : start_cursor + amount_written; descriptor->size = gfd.size; irq = irq_save_disable(); @@ -197,7 +236,7 @@ size_t simple_write(module_root *root, const char *path, const void *buf, size_t seek(&fd, fd.size, SEEK_ABSOLUTE); } size_t res = write_file(&fd, (char*)buf, size); - if (append){ + if (!append){ truncate(&fd, size); } close_file(&fd); @@ -217,7 +256,15 @@ size_t list_directory_contents(module_root *root, const char *path, void* buf, s return 0; } if (!mod->readdir) return 0; - return mod->readdir(search_path, buf, size, offset); + if (mod->owner != get_kernel_proc()->id){ + job_make(job_readdir, mod, { + job_serialize_str(&app, 0, search_path); + job_serialize_buf(&app, 1, true, buf, size, copy_on_end); + job_serialize_off(&app, 3, offset); + }); + return j_ret; + } else + return mod->readdir(search_path, buf, size, offset); } bool get_stat(module_root *root, const char *path, fs_stat *out_stat){ @@ -233,6 +280,13 @@ bool get_stat(module_root *root, const char *path, fs_stat *out_stat){ return false; } if (!mod->getstat) return false; + if (mod->owner != get_kernel_proc()->id){ + job_make(job_stat, mod, { + job_serialize_str(&app, 0, search_path); + job_serialize_stat(&app, 1, out_stat); + }) + return j_ret; + } return mod->getstat(search_path, out_stat); } @@ -251,12 +305,17 @@ bool truncate(file *descriptor, size_t size){ file gfd = (file){ .id = local.mfile_id, - .size = descriptor->size, + .size = size, .cursor = descriptor->cursor, .data_type = descriptor->data_type }; - - if (!local.mod->truncate(&gfd, size)) return false; + + if (local.mod->owner != get_kernel_proc()->id){ + job_make(job_trunc, local.mod, { + job_serialize_fd(&app, 0, &gfd, copy_on_start); + }); + return j_ret; + } else if (!local.mod->truncate(&gfd)) return false; descriptor->size = gfd.size; descriptor->cursor = gfd.cursor; @@ -292,5 +351,5 @@ void close_files_for_process(uint16_t pid){ close_file(&fd); } } - close_pipes_for_process(pid); + close_pipes_for_process(pid);//TODO: pipes need to be cleaned. They're not being used } diff --git a/kernel/filesystem/filesystem.h b/kernel/filesystem/filesystem.h index 112c7844..54c2d786 100644 --- a/kernel/filesystem/filesystem.h +++ b/kernel/filesystem/filesystem.h @@ -11,6 +11,7 @@ extern "C" { FS_RESULT open_file_global(module_root *root, const char* path, file* descriptor, system_module **mod); FS_RESULT open_file(module_root *root, const char* path, file* descriptor); +FS_RESULT instance_local_fd(system_module *mod, file *descriptor); size_t read_file(file *descriptor, char* buf, size_t size); size_t write_file(file *descriptor, const char* buf, size_t size); void close_file_global(file *descriptor, system_module *mod); diff --git a/kernel/filesystem/fsdriver.hpp b/kernel/filesystem/fsdriver.hpp index a11b7a36..8377d738 100644 --- a/kernel/filesystem/fsdriver.hpp +++ b/kernel/filesystem/fsdriver.hpp @@ -14,5 +14,5 @@ class FSDriver { virtual size_t list_contents(const char *path, void* buf, size_t size, file_offset *offset = 0) = 0; virtual void close_file(file* descriptor) = 0; virtual bool stat(const char *path, fs_stat *out_stat) = 0; - virtual bool truncate(file *descriptor, size_t size) = 0; + virtual bool truncate(file *descriptor) = 0; }; \ No newline at end of file diff --git a/kernel/filesystem/modules/fs_isolation.c b/kernel/filesystem/modules/fs_isolation.c index 970d0227..d0e95a4d 100644 --- a/kernel/filesystem/modules/fs_isolation.c +++ b/kernel/filesystem/modules/fs_isolation.c @@ -8,42 +8,43 @@ chunk_array_t *fs_permissions; u64 register_fs_id(){ if (!fs_permissions) fs_permissions = chunk_array_create(sizeof(uptr), 256); - hash_map_t *map = hash_map_create(64); - return chunk_array_push(fs_permissions, &map); + module_root *map = zalloc(sizeof(module_root)); + map->map = hash_map_create(64); + return chunk_array_push(fs_permissions, map); } -hash_map_t* get_fs_for_id(u64 id){ +module_root* get_fs_for_id(u64 id){ if (!fs_permissions) return 0; - return *(hash_map_t**)chunk_array_get(fs_permissions, id); + return (module_root*)chunk_array_get(fs_permissions, id); } -hash_map_t* kernel_modules; +module_root kernel_modules = {}; -hash_map_t* kernel_fs(){ - return kernel_modules; +module_root* kernel_fs(){ + return &kernel_modules; } bool load_module(system_module *module){ - if (!kernel_modules) kernel_modules = hash_map_create(64); - return load_module_to(kernel_modules, module); + if (!kernel_modules.map) kernel_modules.map = hash_map_create(64); + return load_module_to(&kernel_modules, module); } bool unload_module(system_module *module){ - return unload_module_from(kernel_modules, module); + return unload_module_from(&kernel_modules, module); } system_module* get_module(const char **full_path){ - return get_module_from(kernel_modules, full_path); + return get_module_from(&kernel_modules, full_path); } size_t list_root(void* buf, size_t size, uint64_t *offset){ fs_dir_list_helper helper = create_dir_list_helper(buf, size); - return list_root_from(kernel_modules, &helper, offset); + return list_root_from(&kernel_modules, &helper, offset); } string resolve_isolated_path(const char *path, u64 id, module_root *resolved, bool allow_kfs){ if (!path || !resolved || !id) return (string){}; - hash_map_t *localfs = get_fs_for_id(id); + module_root *localfs = get_fs_for_id(id); const char *localpath = path; system_module *localmod = get_module_from(localfs, &localpath); if (!localmod){ @@ -53,7 +54,7 @@ string resolve_isolated_path(const char *path, u64 id, module_root *resolved, bo if (!rootmod){ return (string){}; } - memcpy(resolved,kernel_modules,sizeof(module_root)); + memcpy(resolved,&kernel_modules,sizeof(module_root)); return string_from_literal(path); } if (localmod->alias_info.alias_path.length){ @@ -61,9 +62,14 @@ string resolve_isolated_path(const char *path, u64 id, module_root *resolved, bo const char *rootpath = s.data; system_module *rootmod = get_module(&rootpath); if (!rootmod) return (string){}; - memcpy(resolved,kernel_modules,sizeof(module_root)); + memcpy(resolved,&kernel_modules,sizeof(module_root)); return s; } memcpy(resolved,localfs,sizeof(module_root)); return string_from_literal(path); +} + +void destroy_fs(u64 fsid){ + if (!fsid) return; + //TODO: STUB } \ No newline at end of file diff --git a/kernel/filesystem/modules/fs_isolation.h b/kernel/filesystem/modules/fs_isolation.h index 30bb99b9..e4e754d1 100644 --- a/kernel/filesystem/modules/fs_isolation.h +++ b/kernel/filesystem/modules/fs_isolation.h @@ -3,11 +3,14 @@ #include "data/struct/linked_list.h" #include "files/system_module.h" -typedef hash_map_t module_root; +typedef struct { + hash_map_t *map; + hash_map_t *reserved; +} module_root; u64 register_fs_id(); -hash_map_t* get_fs_for_id(u64 id); -hash_map_t* kernel_fs(); +module_root* get_fs_for_id(u64 id); +module_root* kernel_fs(); #ifdef __cplusplus extern "C" { @@ -21,6 +24,7 @@ size_t list_root(void* buf, size_t size, uint64_t *offset); //Userland string resolve_isolated_path(const char *path, u64 id, module_root *resolved, bool allow_kfs); +void destroy_fs(u64 fsid); #ifdef __cplusplus } diff --git a/kernel/filesystem/modules/module_loader.c b/kernel/filesystem/modules/module_loader.c index f3b112e8..11215acb 100644 --- a/kernel/filesystem/modules/module_loader.c +++ b/kernel/filesystem/modules/module_loader.c @@ -7,6 +7,7 @@ #include "files/dir_list.h" #include "exceptions/exception_handler.h" #include "files/vfs.h" +#include "process/scheduler.h" #define MODULE_STRICT @@ -24,39 +25,63 @@ system_module root_module = { .readdir = 0, }; -bool load_module_to(hash_map_t* modules, system_module *module){ - if (!module->init){ - if (strcmp(module->mount,"/console")) kprintf("[MODULE] module not initialized due to missing initializer");//TODO: can we make printf silently fail so logging becomes easier? +bool reserve_mount_point(module_root* modules, char* mount_point){ + if (!modules->reserved) modules->reserved = hash_map_create(64); + if (hash_map_get_dictionary(modules->reserved, mount_point)){ print("[MODULE] %s already reserved",mount_point); return false; } + hash_map_put_dictionary(modules->reserved, mount_point, (void*)((u64)get_kernel_proc()->id)); + print("[MODULE] Reserved %s",mount_point); + return false; +} + +bool load_module_to(module_root* modules, system_module *module){ + if (module->owner == get_kernel_proc()->id && !module->init){ + if (strcmp(module->mount,"/console")) kprintf("[MODULE error] module not initialized due to missing initializer");//TODO: can we make printf silently fail so logging becomes easier? return false; } if (!module->version){ - string format = string_format("Version number cannot be null for module /%s",module->mount); - if (strcmp(module->mount,"/console")) + string format = string_format("[MODULE error] Version number cannot be null for module /%s",module->mount); + if (strcmp(module->mount,"/console")) { #ifdef MODULE_STRICT - panic(format.data,0); + if (module->owner != get_kernel_proc()->id){ + kprintf(format.data); + } else { + panic(format.data,0); + } #else kprintf(format.data); #endif + } string_free(format); return false; } - if (!module->init(module)){ - if (strcmp(module->mount,"/console")) kprintf("[MODULE] failed to load module %s. Init failed",module->name); + if (!module->owner) module->owner = get_kernel_proc()->id; + if (module->owner == get_kernel_proc()->id && !module->init(module)){ + if (strcmp(module->mount,"/console")) kprintf("[MODULE error] failed to load module %s. Init failed",module->name); return false; } - hash_map_put_dictionary(modules, module->mount, PHYS_TO_VIRT_P(module)); + if (!modules->map) modules->map = hash_map_create(64); + if (modules->reserved && hash_map_get_dictionary(modules->reserved, module->mount)){ + kprintf("[MODULE error] mount point %s is reserved",module->mount); + return false; + } + hash_map_put_dictionary(modules->map, module->mount, PHYS_TO_VIRT_P(module)); return true; } -bool unload_module_from(hash_map_t* modules, system_module *module){ +bool unload_module_from(module_root* modules, system_module *module){ if (!modules) return false; - if (!module->init) return false; - if (module->fini) module->fini(); - hash_map_remove(modules, module->mount, strlen(module->mount), 0); + if (module->owner == get_kernel_proc()->id){ + if (!module->init) return false; + if (module->fini) { + kprint("Can't deinit module yet"); + } else + module->fini(); + } + hash_map_remove(modules->map, module->mount, strlen(module->mount), 0); return false; } -system_module* get_module_from(hash_map_t* modules, const char **full_path){ +system_module* get_module_from(module_root* modules, const char **full_path){ if (!modules) return 0; if (!full_path || !*full_path) return 0; const char *path = *full_path; @@ -78,7 +103,7 @@ system_module* get_module_from(hash_map_t* modules, const char **full_path){ if (!mod_name.length){ return &root_module; } - return hash_map_get(modules, mod_name.data, mod_name.length); + return hash_map_get(modules->map, mod_name.data, mod_name.length); } static u64 index = 0, count = 0; @@ -91,19 +116,20 @@ void iterate_root(void* key, u64 keylen, void* value){ if (count <= index) return; system_module *mod = value; + if (!mod || !mod->mount) return; if (!dir_list_fill(dir_helper, mod->mount)){ if (list_offset) *list_offset = index; return; } } -size_t list_root_from(hash_map_t* modules, fs_dir_list_helper *helper, uint64_t *offset){ +size_t list_root_from(module_root* modules, fs_dir_list_helper *helper, uint64_t *offset){ dir_helper = helper; index = offset ? *offset : 0; count = 0; - hash_map_for_each(modules, iterate_root); + hash_map_for_each(modules->map, iterate_root); return dir_buf_size(helper); } diff --git a/kernel/filesystem/modules/module_loader.h b/kernel/filesystem/modules/module_loader.h index f53a2ea0..82eadcb2 100644 --- a/kernel/filesystem/modules/module_loader.h +++ b/kernel/filesystem/modules/module_loader.h @@ -5,6 +5,7 @@ #include "fs_isolation.h" #include "files/dir_list.h" +bool reserve_mount_point(module_root* modules, char* mount_point); bool load_module_to(module_root* modules, system_module *module); bool unload_module_from(module_root* modules, system_module *module); system_module* get_module_from(module_root* modules, const char **full_path); diff --git a/kernel/filesystem/virtio_9p_pci.cpp b/kernel/filesystem/virtio_9p_pci.cpp index fb266dd7..f13b5718 100644 --- a/kernel/filesystem/virtio_9p_pci.cpp +++ b/kernel/filesystem/virtio_9p_pci.cpp @@ -224,11 +224,11 @@ size_t Virtio9PDriver::list_contents(const char *path, void* buf, size_t size, u return amount; } -bool Virtio9PDriver::truncate(file *descriptor, size_t size){ +bool Virtio9PDriver::truncate(file *descriptor){ module_file *mfile = (module_file*)hash_map_get(open_files, &descriptor->id, sizeof(uint64_t)); if (!mfile) return false; if (mfile->read_only) return false; - if (!set_attribute((u32)mfile->serial, P9_SETATTR_SIZE, size)) return false; + if (!set_attribute((u32)mfile->serial, P9_SETATTR_SIZE, descriptor->size)) return false; if (!sync_file(mfile)) return false; descriptor->size = mfile->file_size; if (descriptor->cursor > descriptor->size) descriptor->cursor = descriptor->size; @@ -588,14 +588,15 @@ void shared_close(file *descriptor){ p9Driver->close_file(descriptor); } -bool shared_truncate(file *descriptor, size_t size){ - return p9Driver->truncate(descriptor, size); +bool shared_truncate(file *descriptor){ + return p9Driver->truncate(descriptor); } system_module p9_fs_module = (system_module){ .name = "9PFS", .mount = "home", .version = VERSION_NUM(0, 1, 0, 0), + .owner = 0, .init = shared_init, .fini = shared_fini, .open = shared_open, diff --git a/kernel/filesystem/virtio_9p_pci.hpp b/kernel/filesystem/virtio_9p_pci.hpp index 8987786b..05b1f01f 100644 --- a/kernel/filesystem/virtio_9p_pci.hpp +++ b/kernel/filesystem/virtio_9p_pci.hpp @@ -14,7 +14,7 @@ class Virtio9PDriver : public FSDriver { size_t list_contents(const char *path, void* buf, size_t size, uint64_t *offset) override; void close_file(file* descriptor) override; bool stat(const char *path, fs_stat *out_stat) override; - bool truncate(file *descriptor, size_t size) override; + bool truncate(file *descriptor) override; private: virtio_device np_dev = {}; size_t choose_version(); diff --git a/kernel/graph/tres.c b/kernel/graph/tres.c index 039af3f4..f5913f91 100644 --- a/kernel/graph/tres.c +++ b/kernel/graph/tres.c @@ -19,12 +19,12 @@ linked_list_t *window_list; window_frame *focused_window; -i32 zoom_scale = 1; +float zoom_scale = 1.f; uint16_t win_ids = 1; bool dirty_windows = false; -int_point global_win_offset; +int_point global_win_offset = {}; draw_ctx non_win_ctx; @@ -53,8 +53,11 @@ gpu_point win_to_screen(window_frame *frame, gpu_point point){ return (gpu_point){}; } +extern process_t *win_system_proc; + gpu_point convert_mouse_position(gpu_point point){ process_t *p = get_current_proc(); + if (p == win_system_proc) return point; linked_list_node_t *node = linked_list_find(window_list, PHYS_TO_VIRT_P(&p->win_id), PHYS_TO_VIRT_P(find_window)); if (node && node->data){ window_frame* frame = (window_frame*)node->data; @@ -111,6 +114,7 @@ void check_collisions(window_frame *frame){ } bool create_window(i32 x, i32 y, u32 width, u32 height){ + height -= TOOLBAR_HEIGHT; irq_flags_t irq = irq_save_disable(); if (win_ids == UINT16_MAX){ irq_restore(irq); @@ -260,7 +264,7 @@ void commit_frame(draw_ctx* frame_ctx, window_frame* frame, bool overwrite_focus memcpy(&non_win_ctx.dirty_rects, frame_ctx->dirty_rects, sizeof(non_win_ctx.dirty_rects)); non_win_ctx.dirty_count = frame_ctx->dirty_count; non_win_ctx.full_redraw = frame_ctx->full_redraw; - composite(&non_win_ctx, (int_point){}, 1, screen_ctx); + composite(&non_win_ctx, (int_point){}, 1, screen_ctx, (gpu_rect){ {0, MENU_HEIGHT}, {screen_ctx->width, screen_ctx->height-MENU_HEIGHT} }); } if (!frame){ linked_list_node_t *node = linked_list_find(window_list, PHYS_TO_VIRT_P(&p->win_id), PHYS_TO_VIRT_P(find_window)); @@ -275,11 +279,18 @@ void commit_frame(draw_ctx* frame_ctx, window_frame* frame, bool overwrite_focus win_ctx.dirty_count = frame_ctx->dirty_count; win_ctx.full_redraw = frame_ctx->full_redraw; - composite(&win_ctx, (int_point){global_win_offset.x + frame->x,global_win_offset.y + frame->y}, zoom_scale, screen_ctx); + composite(&win_ctx, (int_point){ global_win_offset.x + frame->x, global_win_offset.y + frame->y + TOOLBAR_HEIGHT }, zoom_scale, screen_ctx, (gpu_rect){ {0, MENU_HEIGHT}, {screen_ctx->width, screen_ctx->height-MENU_HEIGHT} }); frame_ctx->dirty_count = 0; frame_ctx->full_redraw = false; - +} + +void window_close_process(process_t *proc){ + u16 npid = proc && proc->win_id ? window_fallback_focus(proc->win_id, proc->id) : 0; + if (npid){ + process_t *next = get_proc_by_pid(npid); + if (next && next->focused && next->state != STOPPED && next->id && next->main_thread.pc && next->main_thread.sp && (is_privileged(next) || next->mm.ttbr0)) sys_set_focus(next->id); + } } u16 window_fallback_focus(u16 win_id, u16 skip_id){ @@ -287,8 +298,13 @@ u16 window_fallback_focus(u16 win_id, u16 skip_id){ if (!node || !node->data) return 0; window_frame *frame = node->data; - if (frame->pid != skip_id) - return frame->pid; + if (frame->pid != skip_id){ + process_t *proc = get_proc_by_pid(frame->pid); + if (proc){ + proc->focused = true; + return frame->pid; + } + } process_t *proc = get_all_processes(); while (proc) { @@ -296,6 +312,7 @@ u16 window_fallback_focus(u16 win_id, u16 skip_id){ frame->pid = proc->id; if (proc->graphics_ctx.fb){ frame->win_ctx.fb = proc->graphics_ctx.fb; + proc->focused = true; if (proc->graphics_ctx.width != frame->width || proc->graphics_ctx.height != frame->height){ frame->width = proc->graphics_ctx.width; frame->height = proc->graphics_ctx.height; @@ -325,4 +342,13 @@ void set_window_focus(uint16_t win_id){ void unset_window_focus(){ focused_window = 0; +} + +void refresh_window_info(u16 wid, window_info_t *info){ + linked_list_node_t *node = linked_list_find(window_list, &wid, find_window); + if (!node || !node->data) return; + + window_frame *frame = node->data; + frame->info = *info; + dirty_windows = true; } \ No newline at end of file diff --git a/kernel/graph/tres.h b/kernel/graph/tres.h index b78cbe6e..e1c37088 100644 --- a/kernel/graph/tres.h +++ b/kernel/graph/tres.h @@ -3,6 +3,7 @@ #include "types.h" #include "ui/draw/draw.h" #include "data/struct/linked_list.h" +#include "process/process.h" #ifdef __cplusplus extern "C" { @@ -14,8 +15,13 @@ typedef struct { uint32_t width, height; draw_ctx win_ctx; uint16_t pid; + window_info_t info; } window_frame; +#define MENU_HEIGHT 50 +#define TOOLBAR_HEIGHT 50 +#define BORDER_SIZE 3 + void init_window_manager(); bool create_window(int32_t x, int32_t y, uint32_t width, uint32_t height); @@ -28,9 +34,12 @@ void get_window_ctx(draw_ctx* out_ctx); void commit_frame(draw_ctx* frame_ctx, window_frame* frame, bool overwrite_focus); +void refresh_window_info(u16 wid, window_info_t *info); + u16 window_fallback_focus(u16 win_id, u16 skip_id); void set_window_focus(uint16_t win_id); void unset_window_focus(); +void window_close_process(process_t *proc); gpu_point convert_mouse_position(gpu_point p); diff --git a/kernel/input/input_dispatch.cpp b/kernel/input/input_dispatch.c similarity index 84% rename from kernel/input/input_dispatch.cpp rename to kernel/input/input_dispatch.c index 33643e99..a851d305 100644 --- a/kernel/input/input_dispatch.cpp +++ b/kernel/input/input_dispatch.c @@ -4,6 +4,7 @@ #include "math/math.h" #include "graph/graphics.h" #include "graph/tres.h" +#include "kernel_processes/windows/menu.h" process_t* focused_proc; @@ -36,7 +37,7 @@ bool register_keypress(keypress kp) { } process_t *target = focused_proc; - if (!target || target->state == process::STOPPED || !target->id || !target->pc || !target->sp || (((target->spsr & 0xF) == 0) && !target->mm.ttbr0)) { + if (!target || target->state == STOPPED || !target->id || !target->main_thread.pc || !target->main_thread.sp || (!is_privileged(target) && !target->mm.ttbr0)) { u16 win_id = target ? target->win_id : 0; u16 skip_id = target ? target->id : 0; focused_proc = 0; @@ -47,7 +48,7 @@ bool register_keypress(keypress kp) { } target = focused_proc; - if (!target || target->state == process::STOPPED || !target->id || !target->pc || !target->sp || (((target->spsr & 0xF) == 0) && !target->mm.ttbr0)) { + if (!target || target->state == STOPPED || !target->id || !target->main_thread.pc || !target->main_thread.sp || (!is_privileged(target) && !target->mm.ttbr0)) { focused_proc = 0; return false; } @@ -83,7 +84,7 @@ bool register_scroll(i8 scroll){ void register_event(kbd_event event){ process_t *target = focused_proc; - if (!target || target->state == process::STOPPED || !target->id || !target->pc || !target->sp || (((target->spsr & 0xF) == 0) && !target->mm.ttbr0)) { + if (!target || target->state == STOPPED || !target->id || !target->main_thread.pc || !target->main_thread.sp || (!is_privileged(target) && !target->mm.ttbr0)) { u16 win_id = target ? target->win_id : 0; u16 skip_id = target ? target->id : 0; focused_proc = 0; @@ -94,7 +95,7 @@ void register_event(kbd_event event){ } target = focused_proc; - if (!target || target->state == process::STOPPED || !target->id || !target->pc || !target->sp || (((target->spsr & 0xF) == 0) && !target->mm.ttbr0)) { + if (!target || target->state == STOPPED || !target->id || !target->main_thread.pc || !target->main_thread.sp || (!is_privileged(target) && !target->mm.ttbr0)) { focused_proc = 0; return; } @@ -151,6 +152,10 @@ bool mouse_button_pressed(int mb){ return (last_cursor_state & (1 << mb)) == (1 << mb); } +bool mouse_any_button_pressed(){ + return last_cursor_state; +} + uint16_t sys_subscribe_shortcut_current(keypress kp){ return sys_subscribe_shortcut(get_current_proc_pid(),kp); } @@ -174,26 +179,27 @@ void sys_focus_current(){ void sys_set_focus(int pid){ process_t *target = get_proc_by_pid(pid); - if (!target || target->state == process::STOPPED || !target->id || !target->pc || !target->sp || (((target->spsr & 0xF) == 0) && !target->mm.ttbr0)) return; + if (!target || target->state == STOPPED || !target->id || !target->main_thread.pc || !target->main_thread.sp || (!is_privileged(target) && !target->mm.ttbr0)) return; + if (focused_proc && focused_proc->id == pid) return; if (focused_proc) focused_proc->focused = false; focused_proc = target; focused_proc->focused = true; - kprintf("New focus %i",pid); - if (system_config.use_windows) set_window_focus(focused_proc->win_id); + if (system_config.use_windows){ + set_window_focus(focused_proc->win_id); + refresh_menu(); + } } void sys_unset_focus(bool close){ process_t *proc = focused_proc; - if (proc) proc->focused = false; - focused_proc = 0; - if (system_config.use_windows) unset_window_focus(); - - u16 npid = proc && proc->win_id ? window_fallback_focus(proc->win_id, proc->id) : 0; - if (npid) - { - process_t *next = get_proc_by_pid(npid); - if (next && next->focused && next->state != process::STOPPED && next->id && next->pc && next->sp && ((((next->spsr & 0xF) != 0) || next->mm.ttbr0))) focused_proc = next; + if (!proc) return; + if (proc->focused){ + proc->focused = false; + focused_proc = 0; + if (system_config.use_windows) unset_window_focus(); } + + window_close_process(proc); } u16 sys_get_focused_pid(){ diff --git a/kernel/input/input_dispatch.h b/kernel/input/input_dispatch.h index 129105f2..47fd04cf 100644 --- a/kernel/input/input_dispatch.h +++ b/kernel/input/input_dispatch.h @@ -18,6 +18,7 @@ mouse_input get_raw_mouse_in(); gpu_point get_mouse_pos(); bool mouse_button_pressed(int mb); +bool mouse_any_button_pressed(); uint16_t sys_subscribe_shortcut(uint16_t pid, keypress kp); uint16_t sys_subscribe_shortcut_current(keypress kp); diff --git a/kernel/kernel.c b/kernel/kernel.c index 5783f7cd..7aaa7ab1 100644 --- a/kernel/kernel.c +++ b/kernel/kernel.c @@ -91,6 +91,8 @@ void kernel_main(uint64_t board_type, uint64_t dtb_pa) { } kprint("Kernel initialization finished"); + + reserve_mount_point(kernel_fs(), "menu"); kprint("Starting processes"); @@ -112,7 +114,7 @@ void kernel_main(uint64_t board_type, uint64_t dtb_pa) { load_module(&tool_module); - load_module(&scheduler_module); + init_scheduler(); load_module(&environment_module); diff --git a/kernel/kernel_processes/kprocess_loader.c b/kernel/kernel_processes/kprocess_loader.c index 5aef1e31..3d01e78e 100644 --- a/kernel/kernel_processes/kprocess_loader.c +++ b/kernel/kernel_processes/kprocess_loader.c @@ -9,9 +9,14 @@ #include "memory/memory.h" #include "process/isolated_fs/isolated_fs.h" -__attribute__((noreturn)) static void kernel_process_return_trampoline(int32_t exit_code) { +void kernel_thread_return_trampoline(int32_t exit_code){ + switch_proc(YIELD);//TODO: proper cleanup + while (true){} +} + +void kernel_process_return_trampoline(int32_t exit_code) { stop_current_process(exit_code); - while (1) {} + while (true) {} } process_t *create_kernel_process(const char *name, int (*func)(int argc, char* argv[]), int argc, const char* argv[]){ @@ -33,38 +38,17 @@ process_t *create_kernel_process(const char *name, int (*func)(int argc, char* a name_process(proc, name); - uint64_t stack_size = 0x10000; - - uintptr_t stack = (uintptr_t)palloc(stack_size, MEM_PRIV_KERNEL, MEM_RW, true); - if (!stack) { - reset_process(proc); - irq_restore(irq); - return 0; - } - register_allocation(proc->alloc_map, (void*)stack, stack_size); - uintptr_t heap = (uintptr_t)palloc(PAGE_SIZE, MEM_PRIV_KERNEL, MEM_RW, false); if (!heap) { - free_registered(proc->alloc_map, (void*)stack); reset_process(proc); irq_restore(irq); return 0; } register_allocation(proc->alloc_map, (void*)dmap_pa_to_kva(heap), PAGE_SIZE); - proc->stack = (stack + stack_size); - proc->stack_size = stack_size; - proc->heap_phys = heap; - - proc->sp = proc->stack; - proc->pc = ((uintptr_t)func); - proc->regs[30] = ((uintptr_t)kernel_process_return_trampoline); - proc->spsr = 0x205; - - proc->PROC_X0 = 0; - proc->PROC_X1 = 0; + new_thread(proc, &proc->main_thread, 0x205, (uptr)func); if (argc > 0 && argv) { @@ -79,9 +63,9 @@ process_t *create_kernel_process(const char *name, int (*func)(int argc, char* a uint64_t need = argvs + str_total; need = (need + 0xF) & ~0xFULL; - if (need + 0x20 < stack_size) { + if (need + 0x20 < proc->main_thread.stack_info.size) { - uintptr_t top = proc->stack; + uintptr_t top = proc->main_thread.stack_info.top; uintptr_t base = (top - need) & ~0xFULL; char **kargv = (char**)base; @@ -105,16 +89,16 @@ process_t *create_kernel_process(const char *name, int (*func)(int argc, char* a kargv[argc] = 0; - proc->sp = base; - proc->PROC_X0 = argc; - proc->PROC_X1 = (uintptr_t)kargv; + proc->main_thread.sp = base; + proc->main_thread.PROC_X0 = argc; + proc->main_thread.PROC_X1 = (uintptr_t)kargv; } } make_process_fs(proc, 0); ready_process(proc); - kprintf("Kernel process %s (%i) allocated with address at %llx, stack at %llx-%llx, heap at %llx. %i argument(s)", (uintptr_t)name, proc->id, proc->pc, proc->sp - proc->stack_size, proc->sp, (uaddr_t)dmap_pa_to_kva(proc->heap_phys), argc); + kprintf("[NEW PROC:K] process %s (pid: %i main tid: %i) allocated with address at %llx, stack at %llx-%llx, heap at %llx. %i argument(s)", (uintptr_t)name, proc->id, proc->main_thread.tid, proc->main_thread.pc, proc->main_thread.sp - proc->main_thread.stack_info.size, proc->main_thread.sp, (uaddr_t)dmap_pa_to_kva(proc->heap_phys), argc); irq_restore(irq); return proc; diff --git a/kernel/kernel_processes/kprocess_loader.h b/kernel/kernel_processes/kprocess_loader.h index 62b05b4d..25b45920 100644 --- a/kernel/kernel_processes/kprocess_loader.h +++ b/kernel/kernel_processes/kprocess_loader.h @@ -8,6 +8,8 @@ extern "C" { #include "process/process.h" process_t *create_kernel_process(const char *name, int (*func)(int argc, char* argv[]), int argc, const char* argv[]); +__attribute__((noreturn)) void kernel_thread_return_trampoline(int32_t exit_code); +__attribute__((noreturn)) void kernel_process_return_trampoline(int32_t exit_code); #ifdef __cplusplus } diff --git a/kernel/kernel_processes/windows/dos.c b/kernel/kernel_processes/windows/dos.c index 4701b752..6f02633f 100644 --- a/kernel/kernel_processes/windows/dos.c +++ b/kernel/kernel_processes/windows/dos.c @@ -14,8 +14,7 @@ #include "wincomp.h" #include "ui/color/color.h" #include "utils/cursor/cursor_manager.h" - -#define BORDER_SIZE 3 +#include "menu.h" typedef enum { right_move, left_move, down_move, up_move } dos_movement; u16 move_shortcuts[4]; @@ -32,39 +31,66 @@ u16 paste_s = 0; static dos_mode mode; static draw_ctx *dos_ctx; -extern i32 zoom_scale; +extern float zoom_scale; + +static void draw_solid_window(window_frame *frame, draw_ctx *ctx, int_point fixed_point, gpu_size fixed_size, bool fill, bool use_shadows, bool focused){ + int_point win_point = {fixed_point.x + BORDER_SIZE, fixed_point.y + BORDER_SIZE + TOOLBAR_HEIGHT}; + gpu_size win_size = {fixed_size.width - (BORDER_SIZE*2), fixed_size.height - TOOLBAR_HEIGHT - (BORDER_SIZE*2)}; -static void draw_solid_window(draw_ctx *ctx, int_point fixed_point, gpu_size fixed_size, bool fill){ + if (use_shadows && focused) + rectangle(dos_ctx, (rect_ui_config){ + .border_size = BORDER_SIZE * 1.5, + .border_color = 0x44000000, + }, (common_ui_config){ .point = (int_point){(uint32_t)fixed_point.x,(uint32_t)fixed_point.y}, .size = {fixed_size.width+BORDER_SIZE*1.5,fixed_size.height+BORDER_SIZE*1.5}, }); + DRAW(rectangle(ctx, (rect_ui_config){ .border_size = BORDER_SIZE, - .border_color = system_theme.bg_color + 0x222222 + .border_color = saturate(system_theme.bg_color + 0x222222, focused ? 0 : -90), }, (common_ui_config){ .point = fixed_point, .size = fixed_size, - .background_color = system_theme.bg_color, + .background_color = saturate(system_theme.bg_color + 0x111111, focused ? 0 : -90), .foreground_color = COLOR_WHITE, - }),{ - + }), { + label(ctx, (text_ui_config){ + .slice = { frame->info.name, frame->info.name_length}, + .font_size = 3, + }, (common_ui_config){ + .point = RELATIVE(5, BORDER_SIZE+5), + .size = { parent.size.width-200, 30 }, + .foreground_color = system_theme.accent_color, + }); + bool close_pressed = false; + button(ctx, (rect_ui_config){}, (common_ui_config){ + .point = RELATIVE(parent.size.width - (BORDER_SIZE * 2) - 40 - BORDER_SIZE,BORDER_SIZE), + .size = {30, 30}, + .background_color = 0xFFB40000, + }, &close_pressed); + if (close_pressed){ + send_signal(SIG_QUIT, frame->pid); + } + rectangle(ctx, (rect_ui_config){}, (common_ui_config){ + .point = {fixed_point.x + BORDER_SIZE, fixed_point.y + TOOLBAR_HEIGHT}, + .size = {win_size.width - (BORDER_SIZE), BORDER_SIZE}, + .background_color = 0x33000000, + }); + rectangle(ctx, (rect_ui_config){}, (common_ui_config){ + .point = win_point, + .size = win_size, + .background_color = 0, + .foreground_color = COLOR_WHITE, + }); }); } void draw_window(window_frame *frame){ int_point fixed_point = { global_win_offset.x + frame->x - BORDER_SIZE, global_win_offset.y + frame->y - BORDER_SIZE }; - gpu_size fixed_size = { frame->width + BORDER_SIZE*2, frame->height + BORDER_SIZE*2 }; + gpu_size fixed_size = { frame->width + BORDER_SIZE*2, frame->height + BORDER_SIZE*2 + TOOLBAR_HEIGHT }; fixed_point.x /= zoom_scale; fixed_point.y /= zoom_scale; fixed_size.width /= zoom_scale; fixed_size.height /= zoom_scale; - if (!system_theme.use_window_shadows || focused_window != frame){ - draw_solid_window(dos_ctx, (int_point){(uint32_t)fixed_point.x,(uint32_t)fixed_point.y}, fixed_size, !frame->pid); - return; - } - DRAW(rectangle(dos_ctx, (rect_ui_config){ - .border_size = BORDER_SIZE * 1.5, - .border_color = 0x44000000, - }, (common_ui_config){ .point = (int_point){(uint32_t)fixed_point.x,(uint32_t)fixed_point.y}, .size = {fixed_size.width+BORDER_SIZE*1.5,fixed_size.height+BORDER_SIZE*1.5}, }),{ - draw_solid_window(dos_ctx, (int_point){(uint32_t)fixed_point.x,(uint32_t)fixed_point.y}, fixed_size, !frame->pid); - }); + draw_solid_window(frame, dos_ctx, (int_point){(uint32_t)fixed_point.x,(uint32_t)fixed_point.y}, fixed_size, !frame->pid, system_theme.use_window_shadows, focused_window == frame); } gpu_point click_loc; @@ -72,7 +98,7 @@ window_frame* clicked_frame; static inline void calc_click(void *node){ window_frame* frame = (window_frame*)node; - gpu_point p = win_to_screen(frame, click_loc); + gpu_point p = win_to_screen(frame, click_loc);//TODO: account for zoom if (!p.x || !p.y) return; clicked_frame = frame; } @@ -216,11 +242,16 @@ void check_shortcuts(){ } } +void refresh_desktop_colors(){ + setup_desktop_bg(); + draw_desktop(); + dirty_windows = true; +} + int window_system(){ disable_visual(); dos_ctx = gpu_get_ctx(); - setup_desktop_bg(); - draw_desktop(); + refresh_desktop_colors(); setup_shortcuts(); switch_cursor(cursor_crosshair); @@ -289,19 +320,28 @@ int window_system(){ } drawing = false; } - // i8 scroll = get_raw_mouse_in().scroll; - // if (scroll){ - // zoom_scale += -scroll; - // zoom_scale = clamp(zoom_scale, 1, 5); - // dirty_windows = true; - // } + if (system_theme.use_desktop_zoom){ + i8 scroll = get_raw_mouse_in().scroll; + if (scroll){ + click_loc = get_mouse_pos(); + clicked_frame = 0; + linked_list_for_each(window_list, calc_click); + if (!clicked_frame){ + zoom_scale += -scroll; + zoom_scale = clampf(zoom_scale, 0.25f, 5); + dirty_windows = true; + } + } + } disable_interrupt(); + if (mouse_any_button_pressed()) dirty_windows = true; if (dirty_windows){ active = true; draw_desktop(); linked_list_for_each(window_list, redraw_win); dirty_windows = false; } + draw_menu(); gpu_flush(); enable_interrupt(); if (!active && !dirty_windows && !mouse_button_pressed(LMB) && !mouse_button_pressed(MMB)) msleep(25); @@ -309,6 +349,10 @@ int window_system(){ return 0; } +process_t *win_system_proc; + process_t* create_windowing_system(){ - return create_kernel_process("dos", window_system, 0, 0); -} + if (!win_system_proc) + win_system_proc = create_kernel_process("dos", window_system, 0, 0); + return win_system_proc; +} \ No newline at end of file diff --git a/kernel/kernel_processes/windows/menu.c b/kernel/kernel_processes/windows/menu.c new file mode 100644 index 00000000..2e406121 --- /dev/null +++ b/kernel/kernel_processes/windows/menu.c @@ -0,0 +1,74 @@ +#include "menu.h" + +#include "graphic_types.h" +#include "graph/graphics.h" +#include "graph/tres.h" +#include "theme/theme.h" +#include "syscalls/syscalls.h" +#include "input/input_dispatch.h" +#include "filesystem/modules/fs_isolation.h" +#include "filesystem/filesystem.h" + +#define draw_eye(x_off, blink, eyelid) fb_fill_rect(ctx, rect.point.x + eye_margin + x_off, rect.point.y + (rect.size.height * 0.1), eye_size.width, eye_size.height, (blink) ? eyelid : 0xFFcccccc);\ +fb_fill_rect(ctx, rect.point.x + eye_margin + p.x + x_off, rect.point.y + (rect.size.height * 0.1) + p.y, eye_size.width-pupil_distance.width, eye_size.height-pupil_distance.height, (blink) ? eyelid : 0xFF333333); + +void test_widget(draw_ctx *ctx, gpu_rect rect, color bg){ + + gpu_size eye_size = {rect.size.width * 0.2,rect.size.height * 0.3}; + i32 eye_distance = eye_size.width * 1.1; + i32 eye_margin = (rect.size.width - (eye_size.width*2 + eye_distance))/2; + + gpu_size pupil_distance = {eye_size.width*0.3,eye_size.height*0.3}; + + mouse_data data; + get_mouse_status(&data); + + gpu_point p = get_mouse_pos(); + p.x = p.x * pupil_distance.width/ctx->width; + p.y = p.y * pupil_distance.height/ctx->height; + + draw_eye(0,data.raw.buttons & 1, bg+0x111111); + draw_eye(eye_size.width + eye_distance,(data.raw.buttons >> 1) & 1, bg+0x111111); + + fb_fill_rect(ctx, rect.point.x + eye_margin, rect.size.height - eye_size.height - eye_size.height/3, rect.size.width-(eye_margin*2), eye_size.height-(get_raw_mouse_in().scroll*3), 0xFF222222); + if ((data.raw.buttons >> 2) & 1) fb_fill_rect(ctx, rect.point.x + eye_margin, rect.size.height - eye_size.height/2 - eye_size.height/3, rect.size.width-(eye_margin*2), eye_size.height/2, 0xFF442222); + +} + +bool menu_dirty = true; + +void refresh_menu(){ +#if false + menu_dirty = true; +#endif +} + +void load_menu(){ + process_t *menu_proc = get_proc_by_pid(sys_get_focused_pid()); + if (!menu_proc){ print("[MENU debug] no focused process"); return; } + const char *path = "/menu"; + module_root *localfs = get_fs_for_id(menu_proc->permissions.fs_id); + + if (!localfs) return; + + void *buf = zalloc(0x1000); + u64 off = 0; + size_t s = list_directory_contents(localfs, path, buf, 0x1000, &off); + print("Size of read %x",s); + + print("There are %i entries",*(u32*)buf); +} + +void draw_menu(){ + if (menu_dirty){ + load_menu(); + menu_dirty = false; + } + draw_ctx *screen_ctx = gpu_get_ctx(); + fb_fill_rect(screen_ctx, 0, 0, screen_ctx->width, MENU_HEIGHT, system_theme.bg_color+0x111111); + fb_fill_rect(screen_ctx, 0, MENU_HEIGHT-BORDER_SIZE, screen_ctx->width, BORDER_SIZE, 0x44000000); + + // fb_fill_rect(screen_ctx, screen_ctx->width/2 - 100, 0, screen_ctx->width/2 + 100, MENU_HEIGHT, 0xb4dd13); + + test_widget(screen_ctx, (gpu_rect){{screen_ctx->width/2 - 100, 0}, {200, MENU_HEIGHT}},system_theme.bg_color+0x111111); +} \ No newline at end of file diff --git a/kernel/kernel_processes/windows/menu.h b/kernel/kernel_processes/windows/menu.h new file mode 100644 index 00000000..a37d4d19 --- /dev/null +++ b/kernel/kernel_processes/windows/menu.h @@ -0,0 +1,4 @@ +#pragma once + +void draw_menu(); +void refresh_menu(); \ No newline at end of file diff --git a/kernel/kernel_processes/windows/wincomp.c b/kernel/kernel_processes/windows/wincomp.c index d29f74bb..3cb761cf 100644 --- a/kernel/kernel_processes/windows/wincomp.c +++ b/kernel/kernel_processes/windows/wincomp.c @@ -10,7 +10,7 @@ int_point current_win_offset = {}; void new_managed_window(){ draw_ctx *cur = gpu_get_ctx(); if (!cur) return; - create_window(10 - current_win_offset.x, 10 - current_win_offset.y, cur->width - 20, cur->height - 20); + create_window(10 - current_win_offset.x, 10 - current_win_offset.y + MENU_HEIGHT, cur->width - 20, cur->height - 20 - MENU_HEIGHT); global_win_offset.x = current_win_offset.x; current_win_offset.x -= cur->width; } diff --git a/kernel/memory/mm_process.c b/kernel/memory/mm_process.c index ce6c0c69..8d27e1a3 100644 --- a/kernel/memory/mm_process.c +++ b/kernel/memory/mm_process.c @@ -3,6 +3,7 @@ #include "memory/addr.h" #include "std/memory.h" #include "memory/mm_process.h" +#include "process/stack_manager.h" vma* mm_find_vma(mm_struct *mm, uaddr_t va){ if (!mm) return 0; @@ -29,7 +30,7 @@ bool mm_add_vma(mm_struct *mm, uaddr_t start, uaddr_t end, uint8_t prot, uint8_t for (uint16_t i = mm->vma_count; i > ins; i--) mm->vmas[i] = mm->vmas[i - 1]; - mm->vmas[ins] = (vma){start, end, prot, kind, flags}; + mm->vmas[ins] = (vma){ start, end, prot, kind, flags }; mm->vma_count++; if (ins > 0) { @@ -160,7 +161,7 @@ uaddr_t mm_alloc_mmap(mm_struct *mm, size_t size, uint8_t prot, uint8_t kind, ui return base; } -bool mm_try_handle_page_fault(process_t *proc, uintptr_t far, uint64_t esr) { +bool mm_try_handle_page_fault(process_t *proc, thread_t *current_thread, uintptr_t far, uint64_t esr) { if (!proc || !proc->mm.ttbr0) return false; uint64_t ec = (esr >> 26) & 0x3F; @@ -189,12 +190,13 @@ bool mm_try_handle_page_fault(process_t *proc, uintptr_t far, uint64_t esr) { if (!(m->flags & VMA_FLAG_DEMAND)) return false; if (m->kind == VMA_KIND_STACK) { - uintptr_t sp = proc->sp & ~(PAGE_SIZE - 1); +#if LEGACY_STACK + uintptr_t sp = current_thread->sp & ~(PAGE_SIZE - 1); uintptr_t low = sp > (32 * PAGE_SIZE) ? sp - (32 * PAGE_SIZE) : proc->mm.stack_limit; - if (va_page < low || va_page < proc->mm.stack_limit || va_page >= proc->mm.stack_top) return false; + if (va_page < low || va_page < stack_min_addr || va_page >= stack_max_addr){ print("Out of bounds %llx < %llx | %llx < %llx | %llx >= %llx",va_page,low,va_page,proc->mm.stack_limit,va_page,proc->mm.stack_top); return false; } uintptr_t grow_to = proc->mm.stack_commit; if (va_page < grow_to) grow_to = va_page; - if (((proc->mm.stack_top - grow_to) / PAGE_SIZE) > proc->mm.cap_stack_pages) return false; + if (((proc->mm.stack_top - grow_to) / PAGE_SIZE) > proc->mm.cap_stack_pages){ print("Too many pages"); return false; } for (uintptr_t page = proc->mm.stack_commit - PAGE_SIZE; page >= grow_to; page -= PAGE_SIZE) { paddr_t phys = palloc_inner(PAGE_SIZE, MEM_PRIV_USER, MEM_RW, true, false); if (!phys) { @@ -212,6 +214,10 @@ bool mm_try_handle_page_fault(process_t *proc, uintptr_t far, uint64_t esr) { if (page == 0) break; } proc->mm.stack_commit = grow_to; +#else + paddr_t phys = palloc_inner(PAGE_SIZE, MEM_PRIV_USER, MEM_RW, true, false); + mmu_map_4kb((uint64_t*)proc->mm.ttbr0, va_page, phys, MAIR_IDX_NORMAL, m->prot | MEM_NORM, MEM_PRIV_USER); +#endif mmu_flush_asid(proc->mm.asid); return true; } diff --git a/kernel/memory/mm_process.h b/kernel/memory/mm_process.h index 6a6f3d2b..19ba941c 100644 --- a/kernel/memory/mm_process.h +++ b/kernel/memory/mm_process.h @@ -3,7 +3,8 @@ #include "types.h" #include "memory/page_allocator.h" -typedef struct process process_t; +typedef struct process_t process_t; +typedef struct thread_t thread_t; #define VMA_FLAG_DEMAND 1 #define VMA_FLAG_USERALLOC 2 @@ -55,4 +56,4 @@ vma* mm_find_vma(mm_struct *mm, uaddr_t va); bool mm_add_vma(mm_struct *mm, uaddr_t start, uaddr_t end, uint8_t prot, uint8_t kind, uint8_t flags); bool mm_remove_vma(mm_struct *mm, uaddr_t start, uaddr_t end); uaddr_t mm_alloc_mmap(mm_struct *mm, size_t size, uint8_t prot, uint8_t kind, uint8_t flags); -bool mm_try_handle_page_fault(process_t *proc, uintptr_t far, uint64_t esr); \ No newline at end of file +bool mm_try_handle_page_fault(process_t *proc, thread_t *current_thread, uintptr_t far, uint64_t esr); \ No newline at end of file diff --git a/kernel/memory/page_allocator.c b/kernel/memory/page_allocator.c index 8a8930a5..78919279 100644 --- a/kernel/memory/page_allocator.c +++ b/kernel/memory/page_allocator.c @@ -240,7 +240,7 @@ paddr_t palloc_inner(uint64_t size, uint8_t level, uint8_t attributes, bool full if (prev_page) prev_page->next = curr; prev_page = curr; - memset((void*)PHYS_TO_VIRT(address +sizeof(mem_page)), 0, PAGE_SIZE - sizeof(mem_page)); + memset((void*)PHYS_TO_VIRT(address + sizeof(mem_page)), 0, PAGE_SIZE - sizeof(mem_page)); } else { memset((void*)PHYS_TO_VIRT(address), 0, PAGE_SIZE); } diff --git a/kernel/networking/network.cpp b/kernel/networking/network.cpp index 3eb455fb..c1b7e87e 100644 --- a/kernel/networking/network.cpp +++ b/kernel/networking/network.cpp @@ -90,6 +90,7 @@ system_module net_module = (system_module){ .name = "net", .mount = "net", .version = VERSION_NUM(0, 1, 0, 1), + .owner = 0, .init = network_init, .fini = 0, .open = 0, diff --git a/kernel/process/environment/environment.c b/kernel/process/environment/environment.c index 8675010e..c9a9846d 100644 --- a/kernel/process/environment/environment.c +++ b/kernel/process/environment/environment.c @@ -1,8 +1,13 @@ #include "files/folderfs.h" #include "console/kio.h" +#include "graph/tres.h" +#include "process/scheduler.h" +#include "kernel_processes/windows/menu.h" bool env_loaded = false; +#define DATA_WIN_SIGNATURE DATA_SIGNATURE("WININFO") + typedef struct { u16 procid; } env_data; @@ -48,6 +53,20 @@ FS_RESULT environment_open(u64 id, string_slice file_name, file *fd){ } return FS_RESULT_SUCCESS; } + if (slice_lit_match(file_name, "window", true)){ + fd->id = ((env_type_win & 0xFFFF) << 16) | id; + fd->data_type = DATA_WIN_SIGNATURE; + fd->size = sizeof(window_info_t); + if (!proc->environment.win_buf.buffer) + buffer_map_value(&proc->environment.win_buf, &proc->environment.win_info, sizeof(window_info_t), DATA_WIN_SIGNATURE); + return FS_RESULT_SUCCESS; + } + if (slice_lit_match(file_name, "menu", true)){ + fd->id = ((env_type_menu & 0xFFFF) << 16) | id; + fd->data_type = 0; + fd->size = 0; + return FS_RESULT_SUCCESS; + } return FS_RESULT_NOTFOUND; } @@ -63,6 +82,10 @@ buffer* environment_resolve_fd(file *fd){ return &proc->environment.data; case env_type_structure: return &proc->environment.structure; + case env_type_win: + return &proc->environment.win_buf; + case env_type_menu: + return 0; default: return 0; } return 0; @@ -76,6 +99,8 @@ bool environment_init(system_module *module){ static_entries += make_entry(":id/config", backing_virtual, entry_file, DATA_SIGNATURE("OUTFMT"), (buffer){}) != 0; static_entries += make_entry(":id/data", backing_virtual, entry_file, DATA_SIG_RAW, (buffer){}) != 0; static_entries += make_entry(":id/structure", backing_virtual, entry_file, DATA_SIG_DATA_STRUCT, (buffer){}) != 0; + static_entries += make_entry(":id/window", backing_virtual, entry_file, DATA_WIN_SIGNATURE, (buffer){}) != 0; + static_entries += make_entry(":id/menu", backing_virtual, entry_file, 0, (buffer){}) != 0; return true; } @@ -85,13 +110,27 @@ void register_environment(u16 procid){ folderfs_create_folder(data); } +static inline size_t environment_write(file *fd, const char *buf, size_t size, file_offset offset){ + size_t s = buffer_write_lim(environment_resolve_fd(fd), (void*)buf, size); + u16 file_type = (fd->id >> 16) & 0xFFFF; + if (file_type == env_type_win && s == sizeof(window_info_t)){ + refresh_window_info(get_current_proc()->win_id,(window_info_t*)buf); + } + if (file_type == env_type_menu){ + process_t *menu_proc = get_current_proc(); + if (!menu_proc->focused) return 0; + refresh_menu(); + } + return s; +} + system_module environment_module = { .name = "environment", .mount = "environments", .version = VERSION_NUM(0, 1, 0, 0), .init = environment_init, - .read = folderfs_read , - .write = folderfs_write, + .read = folderfs_read, + .write = environment_write, .getstat = folderfs_stat, .readdir = folderfs_readdir, .open = folderfs_open, diff --git a/kernel/process/environment/environment.h b/kernel/process/environment/environment.h index 2003b100..bc20fe2c 100644 --- a/kernel/process/environment/environment.h +++ b/kernel/process/environment/environment.h @@ -10,8 +10,10 @@ typedef struct { buffer data; buffer structure; buffer config_buf; + window_info_t win_info; + buffer win_buf; } environment_data; -typedef enum { env_type_none, env_type_config, env_type_data, env_type_structure } env_data_types; +typedef enum { env_type_none, env_type_config, env_type_data, env_type_structure, env_type_win, env_type_menu } env_data_types; void register_environment(u16 procid); \ No newline at end of file diff --git a/kernel/process/jobs/job_manager.c b/kernel/process/jobs/job_manager.c new file mode 100644 index 00000000..7878d6e8 --- /dev/null +++ b/kernel/process/jobs/job_manager.c @@ -0,0 +1,211 @@ +#include "job_manager.h" +#include "process/process.h" +#include "process/scheduler.h" +#include "data/struct/linked_list.h" +#include "memory/mmu.h" +#include "memory/addr.h" +#include "memory/memory.h" +#include "filesystem/filesystem.h" + +job_id_t job_id_counter = 1; + +uptr job_kpec = 0; +uptr job_ksp = 0; +sizedptr job_kstack = {}; +extern int syscall_depth; +extern void job_restore_kernel(); +extern uptr job_save_ret(); + +typedef struct { + thread_t *requester; + thread_t *worker; + thread_t kernel_ctx; + sizedptr kstack; + job_id_t id; + job_buffer buffers[8]; + size_t buffer_count; + job_types type; + system_module *mod; +} job_state_t; + +linked_list_t *job_list; + +void *job_page; + +void* job_man_alloc(size_t size){ + return allocate(job_page, size, page_alloc); +} + +job_state_t* job_alloc(){ + if (!job_page) job_page = page_alloc(PAGE_SIZE); + if (!job_list) job_list = linked_list_create_alloc(job_man_alloc, release); + job_state_t *job = job_man_alloc(sizeof(job_state_t)); + job->id = job_id_counter++; + linked_list_push(job_list, job); + return job; +} + +bool prepare_thread(job_state_t *job, system_module *mod, job_application_t application, process_t *proc, thread_t *t){ + uptr entry = 0; + switch (application.type){ + case job_stat: entry = (uptr)mod->getstat; break; + case job_readdir: entry = (uptr)mod->readdir; break; + case job_open: entry = (uptr)mod->open; break; + case job_close: entry = (uptr)mod->close; break; + case job_read: entry = (uptr)mod->read; break; + case job_write: entry = (uptr)mod->write; break; + case job_trunc: entry = (uptr)mod->truncate; break; + default: return false; + } + if (!entry) return false; + new_thread(proc, t, proc->spsr, entry); + size_t total_size = 0; + for (size_t i = 0; i < application.buffer_count; i++) + total_size += application.buffers[i].worker_ptr.size; + size_t num_pages = count_pages(total_size, PAGE_SIZE); + uptr buffers = mm_alloc_mmap(&proc->mm, total_size, MEM_RW, VMA_KIND_SPECIAL, 0); + uptr pbuffers = (uptr)palloc_inner(total_size, MEM_PRIV_SHARED, MEM_RW, true, false); + for (size_t i = 0; i < num_pages; i++){ + mmu_map_4kb(proc->mm.ttbr0, buffers + (i * PAGE_SIZE), pbuffers + (i * PAGE_SIZE), MAIR_IDX_NORMAL, MEM_RW, MEM_PRIV_USER); + register_proc_memory(PHYS_TO_VIRT(pbuffers + (i * PAGE_SIZE)), pbuffers + (i * PAGE_SIZE), MEM_RW, MEM_PRIV_KERNEL); + } + memset((void*)PHYS_TO_VIRT(pbuffers), 0, total_size); + print("[JOB debug] buffers will go to %llx - %llx",buffers,pbuffers); + uptr next_addr_pa = PHYS_TO_VIRT(pbuffers); + uptr next_addr_va = buffers; + + for (size_t i = 0; i < application.buffer_count; i++){ + job_buffer buf = application.buffers[i]; + job->buffers[job->buffer_count++] = buf; + if (buf.sync & copy_on_start && buf.worker_ptr.ptr) + memcpy((void*)next_addr_pa, (void*)buf.worker_ptr.ptr, buf.worker_ptr.size); + t->regs[buf.arg_num] = next_addr_va; + job->buffers[i].worker_ptr.ptr = next_addr_va; + if (buf.explicit_size) + t->regs[buf.arg_num+1] = buf.worker_ptr.size; + next_addr_pa += buf.worker_ptr.size; + next_addr_va += buf.worker_ptr.size; + } + return true; +} + +u64 create_new_job(job_application_t application, system_module *mod, thread_t *kthread){ + process_t *requesting_proc = get_proc_by_pid(application.requesting_pid); + if (!requesting_proc){ + print("[JOB error] Unknown requesting proc %i",application.requesting_pid); + return (job_id_t){}; + } + job_state_t *job = job_alloc(); + job->type = application.type; + job->mod = mod; + thread_t *requester = (thread_t*)get_thread_from_proc(requesting_proc, application.requesting_tid); + if (job_ksp != (uptr)ksp) requester->kstack_top = job_ksp; + job->requester = requester; + process_t *fs_owner = get_proc_by_pid(application.worker_pid); + thread_t *new_t = alloc_thread(); + if (!prepare_thread(job, mod, application, fs_owner, new_t)){ + print("[JOB error] failed to prepare thread for job %i",job->id); + return false; + } + print("[JOB debug] Sync between %i - %i will happen with job %i of type %i using thread %i",requester->pid,application.worker_pid,job->id,application.type,new_t->tid); + new_t->job_id = job->id; + job->worker = new_t; + requester->state = BLOCKED; + if (syscall_depth >= 1){ + print("[JOB debug] kstack has been saved to %llx - %x",job_kstack.ptr,job_kstack.size); + memcpy(&job->kernel_ctx, kthread, sizeof(thread_t)); + job->kernel_ctx.job_id = job->id; + job->kernel_ctx.pc = job_save_ret(); + job->kstack = job_kstack; + } else memset(&job->kernel_ctx, 0, sizeof(thread_t)); + schedule_thread(fs_owner, new_t); + switch_proc(YIELD); + return 0; +} + +job_state_t* get_job_state(job_id_t job_id){ + for (linked_list_node_t *cur = job_list->head; cur && cur->data; cur = cur->next){ + job_state_t *job = cur->data; + if (job->id == job_id) return job; + } + return 0; +} + +void* quick_translate(thread_t *thread, process_t *proc, uptr ptr){ + int status = 0; + uptr addr = mmu_translate(proc->mm.ttbr0, ptr, &status); + if (status){ + uint64_t esr = (0x24ULL << 26) | 0x7ULL; + if (!mm_try_handle_page_fault(proc, thread, ptr, esr)) return 0; + + addr = mmu_translate((uint64_t*)proc->mm.ttbr0, ptr, &status); + if (status) return 0; + } + return (void*)PHYS_TO_VIRT(addr); +} + +extern uptr cpec; + +static inline uptr translate_stack(uptr new_top, uptr ptr){ + return new_top-((uptr)ksp-ptr); +} + +void fulfill_job(job_id_t job_id, u64 ret, thread_t *thread){ + job_state_t *st = get_job_state(job_id); + if (!st) { + print("[JOB error] Could not find id %i",job_id); + return; + } + if (thread->job_id != job_id || st->worker != thread){ + print("[JOB error] termination request by wrong thread %i",thread->tid); + return; + } + process_t *proc = get_proc_by_pid(st->requester->pid); + for (size_t i = 0; i < st->buffer_count; i++){ + job_buffer buf = st->buffers[i]; + if (buf.sync & copy_on_end && buf.worker_ptr.ptr){ + print("[JOB debug] Copy buffer %x into %x",buf.worker_ptr.ptr,buf.orig_ptr.ptr); + void* addr = quick_translate(st->requester, proc, buf.orig_ptr.ptr); + if (!addr) continue; + memcpy(addr, (void*)buf.worker_ptr.ptr, buf.worker_ptr.size); + file *fd = addr; + if (buf.fd){ + print("[JOB DEBUG] fd %i size %i signature %s",fd->id,fd->size,&fd->data_type); + if (st->type == job_open){ + instance_local_fd(st->mod, addr); + } + } + } + } + print("[JOB] %i fulfilled by %i",job_id,thread->tid); + if (st->kernel_ctx.job_id){ + st->kernel_ctx.PROC_X0 = ret; + job_kpec = (uptr)&st->kernel_ctx; + cpec = (uptr)st->requester; + + if (st->kstack.ptr){ + st->kernel_ctx.sp = translate_stack((st->kstack.ptr+0x10000), st->kernel_ctx.sp); + print("[JOB debug] Initial Address %llx",st->kernel_ctx.regs[29]); + st->kernel_ctx.regs[29] = translate_stack((st->kstack.ptr+0x10000), st->kernel_ctx.regs[29]); + + uptr addr = st->kernel_ctx.regs[29]; + uptr fp = 0; + do { + print("[JOB debug] Address %llx",addr); + fp = *(uptr*)addr; + print("[JOB debug] Link %llx",fp); + fp = translate_stack(st->kstack.ptr+0x10000, fp); + print("[JOB debug] In new stack %llx",fp); + *(uptr*)addr = fp; + addr = fp; + } while(addr && (addr & 0xfffff00000000000) == 0xffffc00000000000); + } + st->requester->state = RUNNING; + prepare_process_restore(proc); + job_ksp = st->kstack.ptr+0x10000; + job_restore_kernel(); + } else { + ready_thread(st->requester); + st->requester->PROC_X0 = ret; + } +} \ No newline at end of file diff --git a/kernel/process/jobs/job_manager.h b/kernel/process/jobs/job_manager.h new file mode 100644 index 00000000..f8842116 --- /dev/null +++ b/kernel/process/jobs/job_manager.h @@ -0,0 +1,96 @@ +#pragma once + +#include "files/jobs.h" +#include "process/process.h" + +extern uptr job_kpec; +extern uptr job_ksp; +extern sizedptr job_kstack; +extern void job_save_kernel(); +extern void save_kstack(); + +//TODO: if the owner is the current process, we can downgrade the syscall into a function call without async +#define job_make(job_type,mod,action)\ + thread_t kthread = {};\ + job_kstack = (sizedptr){};\ + job_kpec = (uptr)&kthread;\ + if (!job_ksp) job_ksp = (uptr)ksp;\ + job_save_kernel();\ + print("KStack save to %llx",job_ksp);\ + save_kstack();\ + print("KStack saved to %llx of size %llx from %llx",job_kstack.ptr,job_kstack.size,ksp);\ + process_t *owner_proc = get_proc_by_pid(mod->owner);\ + job_application_t app = (job_application_t){\ + .requesting_pid = get_current_proc()->id,\ + .requesting_tid = get_current_thread()->tid,\ + .worker_pid = owner_proc->id,\ + .type = job_type\ + };\ + action\ + u64 j_ret = create_new_job(app, mod, &kthread);\ + (void)j_ret; + +static inline void job_application_append_buffer(job_application_t *app, job_buffer buf){ + if (app->buffer_count >= MAX_JOB_BUFFERS) return; + app->buffers[app->buffer_count++] = buf; +} + +static inline void job_serialize_str(job_application_t *application, u8 arg_num, const char *str){ + size_t size = strlen(str)+1; + job_buffer buf = { + .worker_ptr = {.ptr = (uptr)str, .size = size}, + .orig_ptr = {.ptr = (uptr)str, .size = size}, + .sync = copy_on_start, + .arg_num = arg_num, + .explicit_size = false + }; + job_application_append_buffer(application, buf); +} + +static inline void job_serialize_buf(job_application_t *application, u8 arg_num, bool explicit_size, void *ptr, size_t size, job_sync_type sync_type){ + job_buffer buf = { + .worker_ptr = {.ptr = (uptr)ptr, .size = size}, + .orig_ptr = {.ptr = (uptr)ptr, .size = size}, + .sync = sync_type, + .arg_num = arg_num, + .explicit_size = explicit_size + }; + job_application_append_buffer(application, buf); +} + +static inline void job_serialize_fd(job_application_t *application, u8 arg_num, file *fd, job_sync_type sync_type){ + job_buffer buf = { + .worker_ptr = {.ptr = (uptr)fd, .size = sizeof(file)}, + .orig_ptr = {.ptr = (uptr)fd, .size = sizeof(file)}, + .sync = sync_type, + .arg_num = arg_num, + .explicit_size = false, + .fd = true + }; + job_application_append_buffer(application, buf); +} + +static inline void job_serialize_stat(job_application_t *application, int arg_num, fs_stat *stat){ + job_buffer buf = { + .worker_ptr = {.ptr = (uptr)stat, .size = sizeof(fs_stat) }, + .orig_ptr = {.ptr = (uptr)stat, .size = sizeof(fs_stat) }, + .sync = copy_on_end, + .arg_num = arg_num, + .explicit_size = false, + }; + job_application_append_buffer(application, buf); +} + +static inline void job_serialize_off(job_application_t *application, int arg_num, file_offset *offset){ + job_buffer buf = { + .worker_ptr = {.ptr = (uptr)offset, .size = sizeof(file_offset *) }, + .orig_ptr = {.ptr = (uptr)offset, .size = sizeof(file_offset *) }, + .sync = copy_on_start | copy_on_end, + .arg_num = arg_num, + .explicit_size = false, + }; + job_application_append_buffer(application, buf); +} + +u64 create_new_job(job_application_t application, system_module *mod, thread_t *kthread); +void fulfill_job(job_id_t job_id, u64 ret, thread_t *thread); diff --git a/kernel/process/jobs/job_save.S b/kernel/process/jobs/job_save.S new file mode 100644 index 00000000..2cbfbb58 --- /dev/null +++ b/kernel/process/jobs/job_save.S @@ -0,0 +1,130 @@ +.global job_save_kernel +job_save_kernel: + msr daifset, #2 + + stp x17, x18, [sp, #-16]! + add x17, sp, #16 +2: + adrp x18, job_kpec + add x18, x18, :lo12:job_kpec + ldr x18, [x18] + +3: + +// Save general-purpose registers x1-x30 +stp x0, x1, [x18, #(8 * 0)] +stp x2, x3, [x18, #(8 * 2)] +stp x4, x5, [x18, #(8 * 4)] +stp x6, x7, [x18, #(8 * 6)] +stp x8, x9, [x18, #(8 * 8)] +stp x10, x11, [x18, #(8 * 10)] +stp x12, x13, [x18, #(8 * 12)] +stp x14, x15, [x18, #(8 * 14)] +str x16, [x18, #(8 * 16)] +ldr x16, [sp, #0] +str x16, [x18, #(8 * 17)] +ldr x16, [sp, #8] +str x16, [x18, #(8 * 18)] +str x19, [x18, #(8 * 19)] +stp x20, x21, [x18, #(8 * 20)] +stp x22, x23, [x18, #(8 * 22)] +stp x24, x25, [x18, #(8 * 24)] +stp x26, x27, [x18, #(8 * 26)] +stp x28, x29, [x18, #(8 * 28)] +str x30, [x18,#(8 * 30)] + +// SP +str x17, [x18, #(8 * 31)] + +//Status bits +mrs x17, spsr_el1 +str x17, [x18, #(8 * 33)] + +add sp, sp, #16 + +ret + +.global save_kstack +save_kstack: + +sub sp, sp, #32 +stp x0, x1, [sp, #0] +stp x21,x30, [sp, #16] + +adrp x0, job_ksp +add x0, x0, :lo12:job_ksp +ldr x0, [x0] + +adrp x1, ksp +add x1, x1, :lo12:ksp +cmp x0, x1 + +b.ne 2f + +mov x1, sp +sub x21, x0, x1 +mov x0, #0x10000 +bl zalloc + +adrp x1, job_kstack +add x1, x1, :lo12:job_kstack +stp x0, x21, [x1, #0] + +add x0,x0,#0x10000 +sub x0,x0,x21 + +mov x1, sp +mov x2, x21 +bl memcpy + +2: +ldp x0, x1, [sp, #0] +ldp x21,x30, [sp, #16] + +add sp, sp, #32 + +ret + +.global job_restore_kernel +job_restore_kernel: + adrp x18, job_kpec + add x18, x18, :lo12:job_kpec + ldr x18, [x18] + // Restore general-purpose registers + ldp x0, x1, [x18, #(8 * 0)] + ldp x2, x3, [x18, #(8 * 2)] + ldp x4, x5, [x18, #(8 * 4)] + ldp x6, x7, [x18, #(8 * 6)] + ldp x8, x9, [x18, #(8 * 8)] + ldp x10, x11, [x18, #(8 * 10)] + ldp x12, x13, [x18, #(8 * 12)] + ldp x14, x15, [x18, #(8 * 14)] + ldr x16, [x18, #(8 * 16)] + ldr x19, [x18, #(8 * 19)] + ldp x20, x21, [x18, #(8 * 20)] + ldp x22, x23, [x18, #(8 * 22)] + ldp x24, x25, [x18, #(8 * 24)] + ldp x26, x27, [x18, #(8 * 26)] + ldp x28, x29, [x18, #(8 * 28)] + ldr x30, [x18, #(8 * 30)] + + ldr x17, [x18, #(8 * 33)] + msr spsr_el1, x17 + lsr x17, x17, #2 + and x17, x17, #0b11 + + ldr x17, [x18, #(8 * 31)] + mov sp, x17 + + ldr x17, [x18, #(8 * 17)] + ldr x30, [x18, #(8 * 32)] + ldr x18, [x18, #(8 * 18)] + + ret + +.global job_save_ret +job_save_ret: + ldr x0, [sp, #8] + + ret + diff --git a/kernel/process/kernel_syscall_impl.c b/kernel/process/kernel_syscall_impl.c index 33d3c694..f9c35be9 100644 --- a/kernel/process/kernel_syscall_impl.c +++ b/kernel/process/kernel_syscall_impl.c @@ -125,7 +125,7 @@ int32_t socket_close(SocketHandle *handle){ FS_RESULT openf(const char* path, file* descriptor){ module_root rootfs = {}; string s = resolve_isolated_path(path, get_current_proc()->permissions.fs_id, &rootfs, true); - if (!s.data || !s.length) return open_file(kernel_fs(), path, descriptor);; + if (!s.data || !s.length) return open_file(kernel_fs(), path, descriptor); FS_RESULT res = open_file(&rootfs, s.data, descriptor); string_free(s); return res; @@ -171,7 +171,7 @@ size_t dir_list(const char *path, void *buf, size_t size, u64 *offset){ if (!s.data || !s.length || strncmp(s.data,"/",s.length) == 0){ size_t ret = 0; fs_dir_list_helper helper = create_dir_list_helper(buf, size); - if (rootfs.buckets != kernel_fs()->buckets){ + if (rootfs.map->buckets != kernel_fs()->map->buckets){ ret += list_root_from(&rootfs, &helper, offset); } if (ret >= size) return ret; diff --git a/kernel/process/loading/elf_file.c b/kernel/process/loading/elf_file.c index d7f0804e..ad6e90b9 100644 --- a/kernel/process/loading/elf_file.c +++ b/kernel/process/loading/elf_file.c @@ -127,14 +127,14 @@ uint8_t elf_to_red_permissions(uint8_t flags){ bool setup_process_args(process_t *proc, int argc, const char *argv[]) { if (!proc || argc < 0) return false; - proc->PROC_X0 = argc; - proc->PROC_X1 = 0; - proc->sp = proc->stack; + proc->main_thread.PROC_X0 = argc; + proc->main_thread.PROC_X1 = 0; + proc->main_thread.sp = proc->main_thread.stack_info.top; if (argc == 0) return true; if (!argv) return false; - size_t stack_size = proc->mm.ttbr0 ? (size_t)(proc->mm.stack_top - proc->mm.stack_limit) : proc->stack_size; + size_t stack_size = proc->mm.ttbr0 ? (size_t)(proc->mm.stack_top - proc->mm.stack_limit) : proc->main_thread.stack_info.size; if (!stack_size) return false; size_t total_str = 0; @@ -150,30 +150,30 @@ bool setup_process_args(process_t *proc, int argc, const char *argv[]) { if (argv_size > stack_size) return false; if (total_str > stack_size - argv_size) return false; - uintptr_t str_base = proc->stack - total_str; + uintptr_t str_base = proc->main_thread.stack_info.top - total_str; if (argc > UACCESS_MAX_ARGV) return false; uintptr_t arg_ptrs[UACCESS_MAX_ARGV + 1] = {}; uintptr_t sp = str_base & ~0xFULL; sp -= argv_size; if (proc->mm.ttbr0) { - proc->PROC_X1 = sp; - proc->sp = sp; + proc->main_thread.PROC_X1 = sp; + proc->main_thread.sp = sp; size_t off = 0; for (int i = 0; i < argc; i++) { size_t len = strlen(argv[i]) + 1; - if (copy_to_user(proc, str_base + off, argv[i], len) != UACCESS_OK) return false; + if (copy_to_user(proc, (thread_t*)proc, str_base + off, argv[i], len) != UACCESS_OK) return false; arg_ptrs[i] = str_base + off; off += len; } arg_ptrs[argc] = 0; - if (copy_to_user(proc, sp, arg_ptrs, argv_size) != UACCESS_OK) return false; + if (copy_to_user(proc, (thread_t*)proc, sp, arg_ptrs, argv_size) != UACCESS_OK) return false; return true; } - paddr_t str_phys = proc->stack_phys - total_str; + paddr_t str_phys = proc->main_thread.stack_info.top - total_str; size_t off = 0; for (int i = 0; i < argc; i++) { size_t len = strlen(argv[i]); @@ -190,8 +190,8 @@ bool setup_process_args(process_t *proc, int argc, const char *argv[]) { uintptr_t *kargv = (uintptr_t*)dmap_pa_to_kva(sp_phys); for (int i = 0; i <= argc; i++) kargv[i] = arg_ptrs[i]; - proc->PROC_X1 = sp; - proc->sp = sp; + proc->main_thread.PROC_X1 = sp; + proc->main_thread.sp = sp; return true; } diff --git a/kernel/process/loading/process_loader.c b/kernel/process/loading/process_loader.c index f14a608f..9b1b74f5 100644 --- a/kernel/process/loading/process_loader.c +++ b/kernel/process/loading/process_loader.c @@ -12,6 +12,7 @@ #include "string/string.h" #include "syscalls/syscall_codes.h" #include "process/isolated_fs/isolated_fs.h" +#include "process/stack_manager.h" typedef struct { uint64_t code_base_start; @@ -315,14 +316,10 @@ process_t* create_process(const char *name, const char *bundle, program_load_dat return 0; } if (!shared_page) { + //TODO: can we make the page auto-generated with the codes for svcs? shared_page = palloc_inner(PAGE_SIZE, MEM_PRIV_SHARED, MEM_EXEC, true, false); - if (!shared_page) { - pfree((void*)dmap_pa_to_kva(dest), code_size); - reset_process(proc); - return 0; - } - memset((void*)dmap_pa_to_kva(shared_page), 0, PAGE_SIZE); - *(uint32_t*)(uintptr_t)dmap_pa_to_kva(shared_page) = aarch64_svc(HALT_CODE); + *(u32*)(uptr)dmap_pa_to_kva(shared_page) = aarch64_svc(HALT_CODE); + *(u32*)(uptr)dmap_pa_to_kva(shared_page+sizeof(u32)) = aarch64_svc(HALT_THREAD_CODE); } // kprintf("Allocated space for process between %x and %x",dest,dest+((code_size + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1))); @@ -371,13 +368,15 @@ process_t* create_process(const char *name, const char *bundle, program_load_dat proc->code = dest; proc->code_size = code_size; - uint64_t stack_max_size = 0x800000; //TODO it shouldnt be fix uint64_t shared_pages = 1; size_t shared_size = shared_pages * PAGE_SIZE; - uaddr_t stack_top = 0x00007FFFFFFFF000ULL; - uaddr_t stack_limit = stack_top - stack_max_size; + + new_thread(proc, &proc->main_thread, 0, entry); + + uaddr_t stack_top = proc->main_thread.stack_info.top; + uaddr_t stack_limit = stack_top - proc->main_thread.stack_info.max; uaddr_t stack_commit = stack_top; - uaddr_t mmap_top = stack_limit - PAGE_SIZE; + uaddr_t mmap_top = stack_min_addr - PAGE_SIZE; uaddr_t shared_base = mmap_top - (shared_size - PAGE_SIZE); uaddr_t mmap_bottom = (max_map + (PAGE_SIZE*4) + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1); @@ -394,29 +393,22 @@ process_t* create_process(const char *name, const char *bundle, program_load_dat proc->mm.stack_limit = stack_limit; proc->mm.stack_commit = stack_commit; - uint64_t total_pages = get_total_user_ram() / PAGE_SIZE; if (!total_pages) total_pages = 1; - proc->mm.cap_stack_pages = stack_max_size / PAGE_SIZE; + proc->mm.cap_stack_pages = (stack_max_addr-stack_min_addr) / PAGE_SIZE; proc->mm.cap_anon_pages = total_pages / 2; if (proc->mm.cap_anon_pages < 128) proc->mm.cap_anon_pages = 128; for (uint64_t i = 0; i < shared_pages; i++) mmu_map_4kb((uint64_t*)ttbr, (uint64_t)(shared_base + (i * PAGE_SIZE)), (paddr_t)(shared_page + (i * PAGE_SIZE)), MAIR_IDX_NORMAL, MEM_EXEC | MEM_NORM, MEM_PRIV_SHARED); mm_add_vma(&proc->mm, shared_base, shared_base + shared_size, MEM_EXEC | MEM_NORM, VMA_KIND_SPECIAL, VMA_FLAG_NOFREE); - mm_add_vma(&proc->mm, proc->mm.stack_limit, proc->mm.stack_top, MEM_RW, VMA_KIND_STACK, VMA_FLAG_DEMAND); - - proc->stack = stack_top; - proc->stack_phys = 0; - proc->stack_size = stack_max_size; + proc->mm.rss_stack_pages = 0; - proc->sp = proc->stack; - - proc->pc = (uintptr_t)(entry); - proc->regs[30] = shared_base; - kprintf("User process %s (%i) allocated at %llx entry=%llx stack=%llx-%llx (phys=%llx-%llx) anon=%llx (phys=%llx)", name, proc->id, proc, (uint64_t)proc->pc, (uint64_t)proc->mm.stack_limit, (uint64_t)proc->mm.stack_top, (uint64_t)proc->stack_phys, (uint64_t)proc->stack_phys, (uint64_t)proc->mm.mmap_bottom, (uint64_t)proc->heap_phys); - proc->spsr = 0; + + proc->shared_page = shared_base; + proc->main_thread.regs[30] = proc->shared_page; + kprintf("[NEW PROC:U]: %s (pid: %i, main tid: %i) allocated at %llx entry=%llx stack=%llx-%llx anon=%llx (phys=%llx)", name, proc->id, proc->main_thread.tid, proc, (uint64_t)proc->main_thread.pc, (uint64_t)proc->mm.stack_limit, (uint64_t)proc->mm.stack_top, (uint64_t)proc->mm.mmap_bottom, (uint64_t)proc->heap_phys); proc->state = BLOCKED; make_process_fs(proc,proc->bundle); diff --git a/kernel/process/process.h b/kernel/process/process.h index 13d37922..b1a2a2cf 100644 --- a/kernel/process/process.h +++ b/kernel/process/process.h @@ -12,6 +12,7 @@ extern "C" { #include "graphic_types.h" #include "signals/signals.h" #include "environment/environment.h" +#include "files/jobs.h" #define INPUT_BUFFER_CAPACITY 64 #define PACKET_BUFFER_CAPACITY 128 @@ -52,24 +53,38 @@ typedef struct { } signal_buffer_t; typedef struct { - u64 fs_id; + u64 fs_id;//Filesystem this process has access to + u64 owned_fs_id;//Filesystem this process owns, not automapped to fs_id due to isolation not being enforced yet } system_permissions; -typedef struct process { - //We use the addresses of these variables to save and restore process state +typedef enum { STOPPED, READY, RUNNING, BLOCKED, SLEEPING } process_state; + +typedef struct { + uptr top; + size_t max; + size_t size; +} stack_t; + +struct thread_t { uint64_t regs[31]; // x0–x30 uintptr_t sp; uintptr_t pc; uint64_t spsr; - //Not used in process saving + //Not used in context saving + stack_t stack_info; + uptr kstack_top; + u16 pid; + u16 tid; + process_state state; + u64 wake_at_msec; + thread_t *next; + job_id_t job_id; +}; + +struct process_t { + thread_t main_thread; uint16_t id; - bool in_ready_queue; - bool sleeping; bool suspended; - uint64_t wake_at_msec; - uintptr_t stack; - paddr_t stack_phys; - uint64_t stack_size; paddr_t heap_phys; kaddr_t output; size_t output_size; @@ -85,13 +100,13 @@ typedef struct process { uaddr_t va; page_index *alloc_map; draw_ctx graphics_ctx; - enum process_state { STOPPED, READY, RUNNING, BLOCKED } state; + process_state state; + u64 spsr; __attribute__((aligned(16))) input_buffer_t input_buffer; __attribute__((aligned(16))) event_buffer_t event_buffer; __attribute__((aligned(16))) packet_buffer_t packet_buffer; __attribute__((aligned(16))) scroll_buffer_t scroll_buffer; - __attribute__((aligned(16))) signal_buffer_t signal_buffer; - __attribute__((aligned(16))) signal_handler signal_handlers[NUMBER_SIGNALS]; + __attribute__((aligned(16))) thread_t signal_handlers[NUMBER_SIGNALS]; uint8_t priority; system_permissions permissions; uint16_t win_id; @@ -102,11 +117,18 @@ typedef struct process { char name[MAX_PROC_NAME_LENGTH]; sizedptr debug_lines; sizedptr debug_line_str; - system_module exposed_fs; + thread_t fs_thread; mm_struct mm; + int thread_count; + int thread_ids; environment_data environment; - struct process *process_next; -} process_t; + uptr shared_page; + process_t *process_next; +}; + +static inline bool is_privileged(process_t *proc){ + return proc->spsr & 0xf; +} //Helper functions for accessing registers mapped to scratch regs #define PROC_X0 regs[0] @@ -122,4 +144,4 @@ typedef struct process { #ifdef __cplusplus } -#endif \ No newline at end of file +#endif diff --git a/kernel/process/procfs.c b/kernel/process/procfs.c new file mode 100644 index 00000000..a5f63293 --- /dev/null +++ b/kernel/process/procfs.c @@ -0,0 +1,375 @@ +#include "procfs.h" +#include "files/dir_list.h" +#include "process.h" +#include "exceptions/irq.h" +#include "console/kio.h" +#include "scheduler.h" +#include "math/math.h" + +extern process_t *process_list; +hash_map_t *proc_opened_files; + +typedef struct { + process_t *proc; + uint16_t pid; +} procfs_owner; + +void* proc_page; + +void* procfs_alloc(size_t size){ + return allocate(proc_page, size, page_alloc); +} + +bool init_procfs(){ + proc_page = page_alloc(PAGE_SIZE*16); + if (!proc_opened_files) { + proc_opened_files = hash_map_create(1024); + proc_opened_files->free = release; + proc_opened_files->alloc = procfs_alloc; + } + return true; +} + +size_t list_processes(void *buf, size_t size, file_offset *offset){ + + if (!buf || !offset || size < sizeof(uint32_t)) return 0; + + fs_dir_list_helper helper = create_dir_list_helper(buf, size); + + process_t *proc = process_list; + if (*offset) { + while (proc && proc->id != *offset) proc = proc->process_next; + } + + while (proc) { + if (proc->id != 0 && proc->state != STOPPED) { + char name[6]; + string_format_buf(name, 6, "%i", proc->id); + + if (!dir_list_fill(&helper, name)){ + if (offset){ + *offset = proc->id; + return dir_buf_size(&helper); + } + } + } + proc = proc->process_next; + } + + return dir_buf_size(&helper); +} + +#define NUM_PROC_FILES 2 + +char* proc_files[NUM_PROC_FILES] = { + "out", + "state" +}; + +size_t list_proc_files(void *buf, size_t size, file_offset *offset){ + + if (!buf || !offset || size < sizeof(uint32_t)) return 0; + + fs_dir_list_helper helper = create_dir_list_helper(buf, size); + + u64 index = offset ? *offset : 0; + + for (int i = index; i < NUM_PROC_FILES; i++){ + kprint(proc_files[i]); + char *name = (char*)((uptr)helper.list + 4 + helper.offset); + if (!dir_list_fill(&helper, proc_files[i])){ + if (offset) *offset = i; + return dir_buf_size(&helper); + } + kprint(name); + } + return dir_buf_size(&helper); +} + +size_t readdir_proc(const char *path, void *buf, size_t size, file_offset *offset){ + irq_flags_t irq = irq_save_disable(); + if (!strlen(path)){ + size_t res = list_processes(buf, size, offset); + irq_restore(irq); + return res; + } + const char *pid_s = seek_to(path, '/'); + path = seek_to(pid_s, '/'); + uint64_t pid = parse_int_u64(pid_s, path - pid_s); + process_t *proc = get_proc_by_pid(pid); + if (!proc) { + irq_restore(irq); + return false; + } + if (!strlen(path)){ + size_t res = list_proc_files(buf, size, offset); + irq_restore(irq); + return res; + } + irq_restore(irq); + return false; +} + +FS_RESULT open_proc(const char *path, file *descriptor){ + uint64_t fid = reserve_fd_gid(path); + irq_flags_t irq = irq_save_disable(); + module_file *mfile = (module_file*)hash_map_get(proc_opened_files, &fid, sizeof(uint64_t)); + if (mfile){ + descriptor->id = mfile->fid; + descriptor->size = mfile->file_size; + descriptor->cursor = 0; + mfile->references++; + procfs_owner *owner_info = (procfs_owner*)mfile->private_data; + if (owner_info && owner_info->proc && owner_info->proc->id == owner_info->pid) owner_info->proc->procfs_refs++; + irq_restore(irq); + return FS_RESULT_SUCCESS; + } + const char *pid_s = seek_to(path, '/'); + path = seek_to(pid_s, '/'); + uint64_t pid = parse_int_u64(pid_s, path - pid_s); + process_t *proc = get_proc_by_pid(pid); + if (!proc) { + irq_restore(irq); + return FS_RESULT_NOTFOUND; + } + descriptor->id = fid; + descriptor->cursor = 0; + module_file *file = procfs_alloc(sizeof(module_file)); + if (!file) { + irq_restore(irq); + return FS_RESULT_DRIVER_ERROR; + } + procfs_owner *owner_info = procfs_alloc(sizeof(procfs_owner)); + if (!owner_info) { + irq_restore(irq); + release(file); + return FS_RESULT_DRIVER_ERROR; + } + owner_info->proc = proc; + owner_info->pid = proc->id; + file->fid = fid; + file->private_data = owner_info; + file->references = 1; + if (strcmp_case(path, "out",true) == 0){ + descriptor->size = proc->output ? proc->output_size : proc->postmortem_output_size; + file->read_only = true; + file->buf = (uptr)(proc->output ? proc->output : proc->postmortem_output); + file->file_buffer = (buffer){ + .buffer = (char*)(proc->output ? proc->output : proc->postmortem_output), + .buffer_size = proc->output ? proc->output_size : proc->postmortem_output_size, + .limit = proc->output ? PROC_OUT_BUF : proc->postmortem_output_size, + .options = proc->output ? buffer_circular : buffer_static, + .cursor = proc->output ? proc->output_size : 0, + }; + proc->procfs_refs++; + } else if (strcmp_case(path, "state",true) == 0){ + descriptor->size = sizeof(proc->state); + file->read_only = true; + file->buf = (uptr)&proc->state; + file->file_buffer = (buffer){ + .buffer = (char*)&proc->state, + .limit = sizeof(proc->state), + .options = buffer_static, + .buffer_size = sizeof(proc->state), + .cursor = 0, + }; + proc->procfs_refs++; + } else { + irq_restore(irq); + release((void*)owner_info); + release(file); + return FS_RESULT_NOTFOUND; + } + file->file_size = descriptor->size; + int put = hash_map_put(proc_opened_files, &descriptor->id, sizeof(uint64_t), file); + irq_restore(irq); + if (put >= 0) return FS_RESULT_SUCCESS; + if ((uintptr_t)file->file_buffer.buffer == (uintptr_t)proc->output || (uintptr_t)file->file_buffer.buffer == (uintptr_t)proc->postmortem_output || (uintptr_t)file->file_buffer.buffer == (uintptr_t)&proc->state) { + if (proc->procfs_refs) proc->procfs_refs--; + } + release((void*)owner_info); + release(file); + return FS_RESULT_DRIVER_ERROR; +} + +bool stat_proc(const char *path, fs_stat *out_stat){ + if (!out_stat) return false; + irq_flags_t irq = irq_save_disable(); + if (!strlen(path)){ + bool res = stat_dir(out_stat); + irq_restore(irq); + return res; + } + const char *pid_s = seek_to(path, '/'); + path = seek_to(pid_s, '/'); + uint64_t pid = parse_int_u64(pid_s, path - pid_s); + process_t *proc = get_proc_by_pid(pid); + if (!proc) { + irq_restore(irq); + return false; + } + if (!strlen(path)){ + bool res = stat_dir(out_stat); + irq_restore(irq); + return res; + } + out_stat->type = entry_file; + if (strcmp_case(path, "out",true) == 0){ + out_stat->size = proc->output_size; + out_stat->data_type = DATA_SIG_TEXT; + } + if (strcmp_case(path, "state",true) == 0){ + out_stat->size = sizeof(proc->state); + out_stat->data_type = DATA_SIG_PROC_ST; + } + irq_restore(irq); + return true; +} + +int find_open_proc_file(void *node, void* key){ + uint64_t *fid = (uint64_t*)key; + module_file *file = (module_file*)node; + if (file->fid == *fid) return 0; + return -1; +} + +int find_open_proc_file_buffer(void *node, void* key){ + uintptr_t *buf = (uintptr_t*)key; + module_file *file = (module_file*)node; + if ((uintptr_t)file->file_buffer.buffer == *buf) return 0; + return -1; +} + +size_t read_proc(file* fd, char *buf, size_t size, file_offset offset){ + if (!proc_opened_files){ + kprint("No files open"); + return 0; + } + irq_flags_t irq = irq_save_disable(); + module_file *file = (module_file*)hash_map_get(proc_opened_files, &fd->id, sizeof(uint64_t)); + if (!file) { + irq_restore(irq); + return 0; + } + size_t s = buffer_read(&file->file_buffer, buf, size, offset); + fd->size = file->file_size; + irq_restore(irq); + return s; +} + +size_t write_proc(file* fd, const char *buf, size_t size, file_offset offset){ + process_t *proc = get_current_proc(); + if (fd->id == FD_OUT){ + if (!proc || !size) return 0; + if (!proc->output) { + proc->output = (kaddr_t)palloc(PROC_OUT_BUF, MEM_PRIV_KERNEL, MEM_RW, true); + if (!proc->output) return 0; + } + irq_flags_t irq = irq_save_disable(); + + buffer file_buffer = { + .buffer = (char*)proc->output, + .buffer_size = proc->output_size, + .limit = PROC_OUT_BUF, + .options = buffer_circular, + .cursor = proc->output_size, + }; + + size = min(size, file_buffer.limit); + size_t written = buffer_write_lim(&file_buffer, buf, size); + + proc->output_size = file_buffer.buffer_size; + fd->size = proc->output_size; + + if (proc_opened_files){ + char fullpath[48] = {}; + string_format_buf(fullpath, sizeof(fullpath), "/%i/out", proc->id); + uint64_t fid = reserve_fd_gid(fullpath); + module_file *file = (module_file*)hash_map_get(proc_opened_files, &fid, sizeof(fid)); + if (file) { + file->buf = (uptr)proc->output; + file->file_buffer.buffer = (char*)proc->output; + file->file_buffer.buffer_size = proc->output_size; + file->file_buffer.limit = PROC_OUT_BUF; + file->file_buffer.cursor = proc->output_size; + file->file_buffer.options = buffer_circular; + file->file_size = proc->output_size; + } + } + + irq_restore(irq); + return written; + } + + if (!proc_opened_files){ + kprint("No files open"); + return 0; + } + irq_flags_t irq = irq_save_disable(); + module_file *file = (module_file*)hash_map_get(proc_opened_files, &fd->id, sizeof(uint64_t)); + bool ro = file && file->read_only; + irq_restore(irq); + if (!file) return 0; + if (ro) return 0; + return 0; +} + +extern bool process_can_reset(process_t *proc); +extern bool process_has_runtime_state(process_t *proc); + +void close_proc(file *fd) { + if (!fd) return; + if (!proc_opened_files) return; + + uint64_t fid = fd->id; + process_t *reset_proc = 0; + irq_flags_t irq = irq_save_disable(); + module_file *mfile = (module_file*)hash_map_get(proc_opened_files, &fid, sizeof(fid)); + if (!mfile) { + irq_restore(irq); + return; + } + + procfs_owner *owner_info = (procfs_owner*)mfile->private_data; + process_t *owner = 0; + if (owner_info && owner_info->proc && owner_info->proc->id == owner_info->pid) owner = owner_info->proc; + if (owner) { + if (owner->procfs_refs) owner->procfs_refs--; + if (process_can_reset(owner) && process_has_runtime_state(owner)) reset_proc = owner; + } + + if (mfile->references > 0) mfile->references--; + if (mfile->references == 0) { + void *owned = mfile->file_buffer.buffer; + buffer_options options = mfile->file_buffer.options; + bool owned_postmortem = owner && owned == (void*)owner->postmortem_output; + hash_map_remove(proc_opened_files, &fid, sizeof(fid), 0); + irq_restore(irq); + if (owned && options == buffer_opt_none && !(reset_proc && owned_postmortem)) { + release(owned); + if (owned_postmortem) { + owner->postmortem_output = 0; + owner->postmortem_output_size = 0; + } + } + if (mfile->private_data) release(mfile->private_data); + release(mfile); + if (reset_proc) reset_process(reset_proc); + return; + } + irq_restore(irq); +} + +system_module procfs_mod = (system_module){ + .name = "scheduler", + .mount = "proc", + .version = VERSION_NUM(0, 1, 0, 1), + .init = init_procfs, + .fini = 0, + .open = open_proc, + .read = read_proc, + .write = write_proc, + .close = close_proc, + .getstat = stat_proc, + .readdir = readdir_proc, +}; diff --git a/kernel/process/procfs.h b/kernel/process/procfs.h new file mode 100644 index 00000000..4949e529 --- /dev/null +++ b/kernel/process/procfs.h @@ -0,0 +1,5 @@ +#pragma once + +#include "files/system_module.h" + +extern system_module procfs_mod; \ No newline at end of file diff --git a/kernel/process/scheduler.c b/kernel/process/scheduler.c index 615d2870..5bab0b64 100644 --- a/kernel/process/scheduler.c +++ b/kernel/process/scheduler.c @@ -10,7 +10,6 @@ #include "data/struct/queue.h" #include "data/struct/linked_list.h" #include "std/memory.h" -#include "math/math.h" #include "memory/mmu.h" #include "process/syscall.h" #include "memory/addr.h" @@ -20,38 +19,47 @@ #include "string/string.h" #include "alloc/allocate.h" #include "files/dir_list.h" +#include "stack_manager.h" +#include "graph/tres.h" extern void save_pc_interrupt(uintptr_t ptr); extern void restore_context(uintptr_t ptr); +void *proc_mem_page; + +static inline void* proc_palloc(size_t s){ + return palloc(s, MEM_PRIV_KERNEL, MEM_RW, true); +} + +static inline void* proc_alloc(size_t s){ + if (!proc_mem_page) proc_mem_page = proc_palloc(PAGE_SIZE); + return allocate(proc_mem_page, s, proc_palloc); +} + +thread_t* alloc_thread(){ + return proc_alloc(sizeof(thread_t)); +} + static process_t *current_proc = 0; static process_t *kernel_proc = 0; static process_t *idle_proc = 0; -static process_t *process_list = 0; +process_t *process_list = 0; uint16_t proc_count = 0; uint16_t next_proc_index = 1; -//TODO maybe use a weighted ready queue based on process priority CQueue ready_queue = {}; linked_list_t sleeping_list = {}; -hash_map_t *proc_opened_files; - -void* proc_page; +extern hash_map_t *proc_opened_files; -typedef struct { - process_t *proc; - uint16_t pid; -} procfs_owner; - -__attribute__((noreturn)) static void idle_entry() { +__attribute__((noreturn)) void idle_entry() { for (;;) { asm volatile("dsb sy" ::: "memory"); asm volatile("wfi"); } } -static bool process_is_known(process_t *proc){ +bool process_is_known(process_t *proc){ if (!proc) return false; if (proc == idle_proc) return true; process_t *it = process_list; @@ -62,37 +70,36 @@ static bool process_is_known(process_t *proc){ return false; } -static bool process_has_runtime_state(process_t *proc){ - return proc && (proc->sp || proc->pc || proc->spsr || proc->stack || proc->heap_phys || proc->mm.ttbr0 || proc->output || proc->alloc_map || proc->bundle || proc->code || proc->code_size || proc->va); +bool process_has_runtime_state(process_t *proc){ + return proc && (proc->main_thread.sp || proc->main_thread.pc || proc->main_thread.spsr || proc->main_thread.stack_info.size || proc->heap_phys || proc->mm.ttbr0 || proc->output || proc->alloc_map || proc->bundle || proc->code || proc->code_size || proc->va); } -static bool process_can_run(process_t *proc){ +bool process_can_run(process_t *proc){ if (!proc) return false; if (!process_is_known(proc) || proc->pending_reset) return false; - if (proc->state == STOPPED || proc->sleeping || proc->suspended || !proc->pc || !proc->sp) return false; - if ((proc->spsr & 0xF) == 0) return !!proc->mm.ttbr0; + if (proc->state == STOPPED || proc->suspended || !proc->main_thread.pc || !proc->main_thread.sp) return false; + if (!is_privileged(proc)) return !!proc->mm.ttbr0; return !proc->mm.ttbr0; } -static bool process_can_reset(process_t *proc){ +bool process_can_reset(process_t *proc){ return proc && proc->state == STOPPED && proc->pending_reset && !proc->procfs_refs; } -static void enqueue_ready_process(process_t *proc){ - if (!proc || proc == idle_proc || proc->in_ready_queue) return; - if (!ready_queue.elem_size) cqueue_init(&ready_queue, 0, sizeof(process_t*),0,0); - if (!cqueue_enqueue(&ready_queue, &proc)) panic("ready enqueue failed", proc->id); - proc->in_ready_queue = true; - proc->state = READY; +void enqueue_ready_thread(thread_t *t){ + if (!t || t->pid == idle_proc->id || t->state == READY) return; + if (!ready_queue.elem_size) cqueue_init(&ready_queue, 0, sizeof(thread_t*),0,0); + t->state = READY; + if (!cqueue_enqueue(&ready_queue, &t)) panic("ready enqueue failed", (t->pid << 16) | t->pid); } -static bool remove_sleeping_process(process_t *proc, uint16_t pid){ +bool remove_sleeping_process(process_t *proc, uint16_t pid){ bool removed = false; linked_list_node_t *sleep = sleeping_list.head; while (sleep) { linked_list_node_t *next = sleep->next; - process_t *sleep_proc = (process_t*)sleep->data; - if (sleep_proc == proc || (sleep_proc && sleep_proc->id == pid)) { + thread_t *thread = (thread_t*)sleep->data; + if (thread && thread->pid == pid) { linked_list_remove(&sleeping_list, sleep); removed = true; } @@ -107,43 +114,57 @@ void save_return_address_interrupt(){ void update_sleep_timer() { if (sleeping_list.head) { - process_t *head_proc = (process_t*)sleeping_list.head->data; - if (head_proc) { + thread_t *head_thread = (thread_t*)sleeping_list.head->data; + if (head_thread) { uint64_t now = timer_now_msec(); - uint64_t wait = head_proc->wake_at_msec > now ? head_proc->wake_at_msec - now : 1; + uint64_t wait = head_thread->wake_at_msec > now ? head_thread->wake_at_msec - now : 1; virtual_timer_reset(wait); virtual_timer_enable(); } else virtual_timer_disable(); } else virtual_timer_disable(); } +extern uptr job_ksp; + void switch_proc(ProcSwitchReason reason) { + syscall_depth = 0; if (proc_count == 0) panic("No processes active", 0); + thread_t *prev_t = (thread_t*)cpec; process_t *prev = current_proc, *next_proc = 0; if (prev && prev->state == RUNNING) { if (prev == idle_proc) prev->state = BLOCKED; - else ready_process(prev); + else if (prev_t->state == RUNNING) enqueue_ready_thread(prev_t); } + thread_t *next_thread = 0; while (!cqueue_is_empty(&ready_queue)) { - process_t *queued = 0; + thread_t *queued = 0; if (!cqueue_dequeue(&ready_queue, &queued)) break; if (!queued) continue; - if (process_is_known(queued)) queued->in_ready_queue = false; - if (queued->state != READY || !process_can_run(queued)) continue; - next_proc = queued; + if (queued->state != READY) continue; + process_t *proc = get_proc_by_pid(queued->pid); + next_proc = (process_t*)proc; + next_thread = queued; + if (!process_can_run(next_proc)) continue; break; } - if (!next_proc && current_proc && current_proc != idle_proc && current_proc->state == RUNNING && process_can_run(current_proc)) next_proc = current_proc; - if (!next_proc) next_proc = idle_proc; + if (!next_proc && current_proc && current_proc != idle_proc && current_proc->state == RUNNING && process_can_run(current_proc)){ + next_proc = current_proc; + next_thread = (thread_t*)cpec; + } + if (!next_proc || !process_can_run(next_proc)){ + next_proc = idle_proc; + next_thread = &idle_proc->main_thread; + } if (!next_proc || !process_can_run(next_proc)) panic("no runnable process", 0); - //if (next_proc == idle_proc && prev != idle_proc) kprint("entering idle"); - + + if (!next_thread || next_thread->pid != next_proc->id) next_thread = &next_proc->main_thread; next_proc->state = RUNNING; + next_thread->state = RUNNING; current_proc = next_proc; - cpec = (uintptr_t)current_proc; + cpec = (uptr)next_thread; if (current_proc == idle_proc) timer_disable(); else { timer_enable(); @@ -154,44 +175,41 @@ void switch_proc(ProcSwitchReason reason) { mmu_swap_ttbr(current_proc->mm.ttbr0 ? ¤t_proc->mm : 0); if (prev && prev != current_proc && prev != idle_proc && process_can_reset(prev)) reset_process(prev); + job_ksp = (uptr)ksp; process_restore(); } void save_syscall_return(uint64_t value){ if (!current_proc) return; - current_proc->PROC_X0 = value; + get_current_thread()->PROC_X0 = value; } -void process_restore(){ - if (!current_proc) panic("process_restore null process", 0); - if (!process_is_known(current_proc)) panic("process_restore unknown process", cpec); - if (current_proc->pending_reset || current_proc->state == STOPPED || !current_proc->pc || !current_proc->sp) { - if (current_proc->mm.ttbr0) { - current_proc->pending_reset = true; - current_proc->state = STOPPED; - current_proc->sleeping = false; - current_proc->in_ready_queue = false; +void prepare_process_restore(process_t *proc){ + current_proc = proc; + if (!proc) panic("process_restore null process", 0); + if (!process_is_known(proc)) panic("process_restore unknown process", cpec); + if (proc->pending_reset || proc->state == STOPPED || !proc->main_thread.pc || !proc->main_thread.sp) { + if (proc->mm.ttbr0) { + proc->pending_reset = true; + proc->state = STOPPED; switch_proc(HALT); panic("process_restore recovery returned", cpec); } panic("process_restore invalid process", cpec); } - if ((current_proc->spsr & 0xF) == 0) { - if (!current_proc->mm.ttbr0) panic("process_restore user process without ttbr0", cpec); - if (current_proc->pc >= HIGH_VA) panic("user pc in kernel VA", current_proc->pc); + + if (!is_privileged(proc)) { + // print("Restoring process %i ttbr0",proc->id); + if (!proc->mm.ttbr0) panic("process_restore user process without ttbr0", proc->id); + if (proc->main_thread.pc >= HIGH_VA) panic("user pc in kernel VA", proc->main_thread.pc); + mmu_swap_ttbr(&proc->mm); mmu_ttbr0_enable_user(); - } else mmu_ttbr0_disable_user(); - if (current_proc->signal_buffer.read_index != current_proc->signal_buffer.write_index){ - signal_info_t *info = ¤t_proc->signal_buffer.entries[current_proc->signal_buffer.read_index];//TODO: Wrong, this should be copied into userland mem - current_proc->signal_buffer.read_index = (current_proc->signal_buffer.read_index + 1) % INPUT_BUFFER_CAPACITY; - if (can_signal_be_handled(info->type)){ - signal_handler handler = current_proc->signal_handlers[info->type]; - if (handler) handler(info); - else handle_signal_default(current_proc, info); - } else handle_signal_default(current_proc, info); - switch_proc(RECV_SIGNAL);//TODO: wasteful, we might have a lot of CPU time left for this proc to use - } else - restore_context(cpec); + } else mmu_ttbr0_disable_user(); +} + +void process_restore(){ + prepare_process_restore(current_proc); + restore_context(cpec); } bool start_scheduler(){ @@ -203,34 +221,28 @@ bool start_scheduler(){ return true; } -void* procfs_alloc(size_t size){ - return allocate(proc_page, size, page_alloc); -} - -bool init_scheduler_module(){ - if (!proc_opened_files) { - proc_opened_files = hash_map_create(1024); - proc_opened_files->free = release; - proc_opened_files->alloc = procfs_alloc; - } - if (!ready_queue.elem_size) cqueue_init(&ready_queue, 0, sizeof(process_t*),0,0); +bool init_scheduler(){ + load_module(&procfs_mod); return true; } - uintptr_t get_current_heap(){ if (current_proc->heap_phys) return (uintptr_t)dmap_pa_to_kva(current_proc->heap_phys); return current_proc->mm.mmap_bottom; } bool get_current_privilege(){ - return current_proc && (current_proc->spsr & 0b1111) != 0; + return current_proc && is_privileged(current_proc); } process_t* get_current_proc(){ return current_proc; } +thread_t* get_current_thread(){ + return (thread_t*)cpec; +} + process_t* get_kernel_proc(){ return kernel_proc; } @@ -245,12 +257,26 @@ bool scheduler_in_idle(){ void ready_process(process_t *proc){ irq_flags_t irq = irq_save_disable(); - if (!proc || !proc->id || proc->state == STOPPED || proc->sleeping || proc->in_ready_queue || proc->pending_reset) { + if (!proc || !proc->id || proc->state == STOPPED || proc->pending_reset) { irq_restore(irq); return; } - enqueue_ready_process(proc); + proc->spsr = proc->main_thread.spsr; + + enqueue_ready_thread(&proc->main_thread); + proc->state = READY; + irq_restore(irq); +} + +void ready_thread(thread_t *t){ + irq_flags_t irq = irq_save_disable(); + if (!t || !t->pid || !t->tid || t->state == STOPPED || t->state == SLEEPING/* || proc->pending_reset*/) { + irq_restore(irq); + return; + } + + enqueue_ready_thread(t); irq_restore(irq); } @@ -263,6 +289,15 @@ process_t* get_proc_by_pid(uint16_t pid){ return NULL; } +thread_t* get_thread_from_proc(process_t *proc, u16 tid){ + thread_t *t = &proc->main_thread; + do { + if (t->tid == tid) return t; + t = t->next; + } while (t); + return 0; +} + uint16_t get_current_proc_pid(){ return current_proc ? current_proc->id : 0; } @@ -274,22 +309,22 @@ void reset_process(process_t *proc){ uint16_t pid = proc->id; int32_t exit_code = proc->exit_code; - bool counted = proc->sp || proc->pc || proc->spsr || proc->stack || proc->heap_phys || proc->mm.ttbr0; + bool counted = proc->main_thread.sp || proc->main_thread.pc || proc->main_thread.spsr || proc->main_thread.stack_info.size || proc->heap_phys || proc->mm.ttbr0; irq_flags_t irq = irq_save_disable(); proc->pending_reset = false; - proc->sleeping = false; - proc->wake_at_msec = 0; - proc->in_ready_queue = false; + proc->thread_count = 0;//TODO: clean up all threads + proc->thread_ids = 0; remove_sleeping_process(proc, pid); update_sleep_timer(); irq_restore(irq); - proc->sp = 0; - proc->pc = 0; - proc->spsr = 0; - memset(proc->regs, 0, 31 * sizeof(proc->regs[0])); + proc->main_thread.sp = 0; + proc->main_thread.pc = 0; + proc->main_thread.spsr = 0; + unmap_stack(proc, proc->main_thread.stack_info); + memset(proc->main_thread.regs, 0, 31 * sizeof(proc->main_thread.regs[0])); memset(&proc->input_buffer, 0, sizeof(proc->input_buffer)); memset(&proc->event_buffer, 0, sizeof(proc->event_buffer)); proc->packet_buffer.read_index = 0; @@ -364,7 +399,7 @@ void reset_process(process_t *proc){ fid = reserve_fd_gid(proc_path); module_file *state_file = (module_file*)hash_map_get(proc_opened_files, &fid, sizeof(fid)); if (state_file && (uintptr_t)state_file->file_buffer.buffer == (uintptr_t)&proc->state) { - enum process_state *snapshot = (enum process_state*)zalloc(sizeof(proc->state)); + process_state *snapshot = (process_state*)zalloc(sizeof(proc->state)); if (snapshot) { *snapshot = STOPPED; state_file->buf = (uptr)snapshot; @@ -430,16 +465,12 @@ void reset_process(process_t *proc){ proc->mm.ttbr0 = 0; proc->mm.ttbr0_phys = 0; } - if (proc->exposed_fs.init){ - unload_module(&proc->exposed_fs); - } - proc->exposed_fs = (system_module){0}; + destroy_fs(proc->permissions.fs_id); + destroy_fs(proc->permissions.owned_fs_id); memset(proc->name, 0, sizeof(proc->name)); - proc->stack = 0; - proc->stack_phys = 0; - proc->stack_size = 0; + proc->main_thread.stack_info = (stack_t){}; proc->heap_phys = 0; memset(&proc->mm, 0, sizeof(proc->mm)); @@ -464,8 +495,6 @@ void reset_process(process_t *proc){ } void init_main_process(){ - proc_page = page_alloc(PAGE_SIZE*16); - if (!ready_queue.elem_size) cqueue_init(&ready_queue, 0, sizeof(process_t*),0,0); size_t kernel_proc_size = (sizeof(process_t) + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1); kernel_proc = (process_t*)palloc(kernel_proc_size, MEM_PRIV_KERNEL, MEM_RW, true); if (!kernel_proc) panic("kernel process alloc failed", 0); @@ -478,25 +507,15 @@ void init_main_process(){ kernel_proc->id = next_proc_index++; kernel_proc->alloc_map = make_page_index(); kernel_proc->state = BLOCKED; - kernel_proc->heap_phys = (uintptr_t)palloc(0x1000, MEM_PRIV_KERNEL, MEM_RW, false); - kernel_proc->stack_size = 0x10000; - kernel_proc->stack = (uintptr_t)palloc(kernel_proc->stack_size,MEM_PRIV_KERNEL, MEM_RW,true); - kernel_proc->sp = (uintptr_t)ksp; - kernel_proc->output = (kaddr_t)palloc(PROC_OUT_BUF, MEM_PRIV_KERNEL, MEM_RW, true); - kernel_proc->output_size = 0; - kernel_proc->postmortem_output = 0; - kernel_proc->postmortem_output_size = 0; + + new_thread(kernel_proc, &kernel_proc->main_thread, 0x205, 0); + kernel_proc->priority = PROC_PRIORITY_LOW; name_process(kernel_proc, "kernel"); idle_proc->state = BLOCKED; idle_proc->priority = PROC_PRIORITY_LOW; - idle_proc->stack_size = 0x4000; - uintptr_t idle_stack = (uintptr_t)palloc(idle_proc->stack_size,MEM_PRIV_KERNEL, MEM_RW,true); - if (!idle_stack) panic("idle stack alloc failed", 0); - idle_proc->stack = idle_stack + idle_proc->stack_size; - idle_proc->sp = idle_proc->stack; - idle_proc->pc = (uintptr_t)idle_entry; - idle_proc->spsr = 0x205; + + new_thread(idle_proc, &idle_proc->main_thread, 0x205, (uptr)idle_entry); name_process(idle_proc, "idle"); proc_count++; @@ -522,9 +541,6 @@ process_t* init_process(){ proc->exit_code = 0; proc->state = BLOCKED; proc->priority = PROC_PRIORITY_LOW; - proc->in_ready_queue = false; - proc->sleeping = false; - proc->wake_at_msec = 0; proc->pending_reset = false; proc_count++; irq_restore(irq); @@ -583,11 +599,10 @@ void stop_process(uint16_t pid, int32_t exit_code){ kprintf("[SCHEDULER] Stop process %i with code %i",proc->id,proc->exit_code); - proc->in_ready_queue = false; - proc->sleeping = false; - proc->wake_at_msec = 0; if (proc->focused) sys_unset_focus(false); + else + window_close_process(proc); remove_sleeping_process(proc, pid); update_sleep_timer(); @@ -596,6 +611,8 @@ void stop_process(uint16_t pid, int32_t exit_code){ return; } + //TODO: any threads for this process with a job id need to be reported back as failed + if (proc->mm.ttbr0) mmu_swap_ttbr(0); switch_proc(HALT); panic("stop_process returned", pid); @@ -611,7 +628,7 @@ void block_process(process_t *proc){ void resume_blocked_process(process_t *proc){ proc->suspended = false; - enqueue_ready_process(proc); + enqueue_ready_thread(&proc->main_thread); } uint16_t process_count(){ @@ -622,7 +639,7 @@ process_t *get_all_processes(){ return process_list; } -void sleep_process(uint64_t msec){ +void sleep_thread(uint64_t msec){ irq_flags_t irq = irq_save_disable(); if (!msec) { @@ -632,20 +649,20 @@ void sleep_process(uint64_t msec){ } uint64_t wake_at = timer_now_msec() + msec; - current_proc->state = BLOCKED; - current_proc->sleeping = true; - current_proc->wake_at_msec = wake_at; + thread_t *current_thread = (thread_t*)cpec; + current_thread->state = SLEEPING; + current_thread->wake_at_msec = wake_at; linked_list_node_t *it = sleeping_list.head, *prev = 0; while (it) { - process_t *cur = (process_t*)it->data; + thread_t *cur = (thread_t*)it->data; if (!cur || cur->wake_at_msec > wake_at) break; prev = it; it = it->next; } - linked_list_insert_after(&sleeping_list, prev, current_proc); - if (sleeping_list.head && sleeping_list.head->data == current_proc){ + linked_list_insert_after(&sleeping_list, prev, current_thread); + if (sleeping_list.head && sleeping_list.head->data == current_thread){ virtual_timer_reset(msec); virtual_timer_enable(); } @@ -653,45 +670,24 @@ void sleep_process(uint64_t msec){ irq_restore(irq); } -void wake_process(process_t *proc){ - if (!proc) return; - irq_flags_t irq = irq_save_disable(); - - if (proc->state == STOPPED) { - irq_restore(irq); - return; - } - - if (remove_sleeping_process(proc, proc->id)) { - proc->sleeping = false; - proc->wake_at_msec = 0; - - if (proc->state == BLOCKED) enqueue_ready_process(proc); - } - - update_sleep_timer(); - irq_restore(irq); -} - void wake_processes(){ irq_flags_t irq = irq_save_disable(); uint64_t now = timer_now_msec(); while (sleeping_list.head) { - process_t *proc = (process_t*)sleeping_list.head->data; + thread_t *t = (thread_t*)sleeping_list.head->data; - if (!proc) { + if (!t) { linked_list_pop_front(&sleeping_list); continue; } - if (proc->wake_at_msec > now) break; - proc = (process_t*)linked_list_pop_front(&sleeping_list); + if (t->wake_at_msec > now) break; + t = (thread_t*)linked_list_pop_front(&sleeping_list); - if (proc) { - proc->sleeping = false; - proc->wake_at_msec = 0; + if (t) { + t->wake_at_msec = 0; - if (proc->state != STOPPED) enqueue_ready_process(proc); + if (t->state != STOPPED) enqueue_ready_thread(t); } } @@ -699,354 +695,39 @@ void wake_processes(){ irq_restore(irq); } -bool load_process_module(process_t *p, system_module *m){ - p->exposed_fs = *m; - p->exposed_fs.init = PHYS_TO_VIRT_P(p->code + ((uintptr_t)p->exposed_fs.init - (uintptr_t)p->va)); - p->exposed_fs.fini = PHYS_TO_VIRT_P(p->code + ((uintptr_t)p->exposed_fs.fini - (uintptr_t)p->va)); - p->exposed_fs.open = PHYS_TO_VIRT_P(p->code + ((uintptr_t)p->exposed_fs.open - (uintptr_t)p->va)); - p->exposed_fs.read = PHYS_TO_VIRT_P(p->code + ((uintptr_t)p->exposed_fs.read - (uintptr_t)p->va)); - p->exposed_fs.write = PHYS_TO_VIRT_P(p->code + ((uintptr_t)p->exposed_fs.write - (uintptr_t)p->va)); - p->exposed_fs.close = PHYS_TO_VIRT_P(p->code + ((uintptr_t)p->exposed_fs.close - (uintptr_t)p->va)); - return load_module(&p->exposed_fs); -} - -size_t list_processes(void *buf, size_t size, file_offset *offset){ - - if (!buf || !offset || size < sizeof(uint32_t)) return 0; - - fs_dir_list_helper helper = create_dir_list_helper(buf, size); - - process_t *proc = process_list; - if (*offset) { - while (proc && proc->id != *offset) proc = proc->process_next; - } - - while (proc) { - if (proc->id != 0 && proc->state != STOPPED) { - char name[6]; - string_format_buf(name, 6, "%i", proc->id); - - if (!dir_list_fill(&helper, name)){ - if (offset){ - *offset = proc->id; - return dir_buf_size(&helper); - } - } - } - proc = proc->process_next; - } - - return dir_buf_size(&helper); -} - -#define NUM_PROC_FILES 2 - -char* proc_files[NUM_PROC_FILES] = { - "out", - "state" -}; - -size_t list_proc_files(void *buf, size_t size, file_offset *offset){ - - if (!buf || !offset || size < sizeof(uint32_t)) return 0; - - fs_dir_list_helper helper = create_dir_list_helper(buf, size); - - u64 index = offset ? *offset : 0; - - for (int i = index; i < NUM_PROC_FILES; i++){ - kprint(proc_files[i]); - char *name = (char*)((uptr)helper.list + 4 + helper.offset); - if (!dir_list_fill(&helper, proc_files[i])){ - if (offset) *offset = i; - return dir_buf_size(&helper); - } - kprint(name); - } - return dir_buf_size(&helper); -} - -size_t readdir_proc(const char *path, void *buf, size_t size, file_offset *offset){ - irq_flags_t irq = irq_save_disable(); - if (!strlen(path)){ - size_t res = list_processes(buf, size, offset); - irq_restore(irq); - return res; - } - const char *pid_s = seek_to(path, '/'); - path = seek_to(pid_s, '/'); - uint64_t pid = parse_int_u64(pid_s, path - pid_s); - process_t *proc = get_proc_by_pid(pid); - if (!proc) { - irq_restore(irq); - return false; - } - if (!strlen(path)){ - size_t res = list_proc_files(buf, size, offset); - irq_restore(irq); - return res; - } - irq_restore(irq); - return false; -} - -FS_RESULT open_proc(const char *path, file *descriptor){ - uint64_t fid = reserve_fd_gid(path); - irq_flags_t irq = irq_save_disable(); - module_file *mfile = (module_file*)hash_map_get(proc_opened_files, &fid, sizeof(uint64_t)); - if (mfile){ - descriptor->id = mfile->fid; - descriptor->size = mfile->file_size; - descriptor->cursor = 0; - mfile->references++; - procfs_owner *owner_info = (procfs_owner*)mfile->private_data; - if (owner_info && owner_info->proc && owner_info->proc->id == owner_info->pid) owner_info->proc->procfs_refs++; - irq_restore(irq); - return FS_RESULT_SUCCESS; - } - const char *pid_s = seek_to(path, '/'); - path = seek_to(pid_s, '/'); - uint64_t pid = parse_int_u64(pid_s, path - pid_s); - process_t *proc = get_proc_by_pid(pid); - if (!proc) { - irq_restore(irq); - return FS_RESULT_NOTFOUND; - } - descriptor->id = fid; - descriptor->cursor = 0; - module_file *file = procfs_alloc(sizeof(module_file)); - if (!file) { - irq_restore(irq); - return FS_RESULT_DRIVER_ERROR; - } - procfs_owner *owner_info = procfs_alloc(sizeof(procfs_owner)); - if (!owner_info) { - irq_restore(irq); - release(file); - return FS_RESULT_DRIVER_ERROR; - } - owner_info->proc = proc; - owner_info->pid = proc->id; - file->fid = fid; - file->private_data = owner_info; - file->references = 1; - if (strcmp_case(path, "out",true) == 0){ - descriptor->size = proc->output ? proc->output_size : proc->postmortem_output_size; - file->read_only = true; - file->buf = (uptr)(proc->output ? proc->output : proc->postmortem_output); - file->file_buffer = (buffer){ - .buffer = (char*)(proc->output ? proc->output : proc->postmortem_output), - .buffer_size = proc->output ? proc->output_size : proc->postmortem_output_size, - .limit = proc->output ? PROC_OUT_BUF : proc->postmortem_output_size, - .options = proc->output ? buffer_circular : buffer_static, - .cursor = proc->output ? proc->output_size : 0, - }; - proc->procfs_refs++; - } else if (strcmp_case(path, "state",true) == 0){ - descriptor->size = sizeof(proc->state); - file->read_only = true; - file->buf = (uptr)&proc->state; - file->file_buffer = (buffer){ - .buffer = (char*)&proc->state, - .limit = sizeof(proc->state), - .options = buffer_static, - .buffer_size = sizeof(proc->state), - .cursor = 0, - }; - proc->procfs_refs++; - } else { - irq_restore(irq); - release((void*)owner_info); - release(file); - return FS_RESULT_NOTFOUND; - } - file->file_size = descriptor->size; - int put = hash_map_put(proc_opened_files, &descriptor->id, sizeof(uint64_t), file); - irq_restore(irq); - if (put >= 0) return FS_RESULT_SUCCESS; - if ((uintptr_t)file->file_buffer.buffer == (uintptr_t)proc->output || (uintptr_t)file->file_buffer.buffer == (uintptr_t)proc->postmortem_output || (uintptr_t)file->file_buffer.buffer == (uintptr_t)&proc->state) { - if (proc->procfs_refs) proc->procfs_refs--; - } - release((void*)owner_info); - release(file); - return FS_RESULT_DRIVER_ERROR; -} - -bool stat_proc(const char *path, fs_stat *out_stat){ - if (!out_stat) return false; - irq_flags_t irq = irq_save_disable(); - if (!strlen(path)){ - bool res = stat_dir(out_stat); - irq_restore(irq); - return res; - } - const char *pid_s = seek_to(path, '/'); - path = seek_to(pid_s, '/'); - uint64_t pid = parse_int_u64(pid_s, path - pid_s); - process_t *proc = get_proc_by_pid(pid); - if (!proc) { - irq_restore(irq); - return false; - } - if (!strlen(path)){ - bool res = stat_dir(out_stat); - irq_restore(irq); - return res; - } - out_stat->type = entry_file; - if (strcmp_case(path, "out",true) == 0){ - out_stat->size = proc->output_size; - out_stat->data_type = DATA_SIG_TEXT; - } - if (strcmp_case(path, "state",true) == 0){ - out_stat->size = sizeof(proc->state); - out_stat->data_type = DATA_SIG_PROC_ST; - } - irq_restore(irq); - return true; -} - -int find_open_proc_file(void *node, void* key){ - uint64_t *fid = (uint64_t*)key; - module_file *file = (module_file*)node; - if (file->fid == *fid) return 0; - return -1; -} - -int find_open_proc_file_buffer(void *node, void* key){ - uintptr_t *buf = (uintptr_t*)key; - module_file *file = (module_file*)node; - if ((uintptr_t)file->file_buffer.buffer == *buf) return 0; - return -1; -} - -size_t read_proc(file* fd, char *buf, size_t size, file_offset offset){ - if (!proc_opened_files){ - kprint("No files open"); - return 0; - } - irq_flags_t irq = irq_save_disable(); - module_file *file = (module_file*)hash_map_get(proc_opened_files, &fd->id, sizeof(uint64_t)); - if (!file) { - irq_restore(irq); - return 0; - } - size_t s = buffer_read(&file->file_buffer, buf, size, offset); - fd->size = file->file_size; - irq_restore(irq); - return s; -} - -size_t write_proc(file* fd, const char *buf, size_t size, file_offset offset){ - process_t *proc = get_current_proc(); - if (fd->id == FD_OUT){ - if (!proc || !size) return 0; - if (!proc->output) { - proc->output = (kaddr_t)palloc(PROC_OUT_BUF, MEM_PRIV_KERNEL, MEM_RW, true); - if (!proc->output) return 0; - } - irq_flags_t irq = irq_save_disable(); - - buffer file_buffer = { - .buffer = (char*)proc->output, - .buffer_size = proc->output_size, - .limit = PROC_OUT_BUF, - .options = buffer_circular, - .cursor = proc->output_size, - }; - - size = min(size, file_buffer.limit); - size_t written = buffer_write_lim(&file_buffer, buf, size); - - proc->output_size = file_buffer.buffer_size; - fd->size = proc->output_size; - - if (proc_opened_files){ - char fullpath[48] = {}; - string_format_buf(fullpath, sizeof(fullpath), "/%i/out", proc->id); - uint64_t fid = reserve_fd_gid(fullpath); - module_file *file = (module_file*)hash_map_get(proc_opened_files, &fid, sizeof(fid)); - if (file) { - file->buf = (uptr)proc->output; - file->file_buffer.buffer = (char*)proc->output; - file->file_buffer.buffer_size = proc->output_size; - file->file_buffer.limit = PROC_OUT_BUF; - file->file_buffer.cursor = proc->output_size; - file->file_buffer.options = buffer_circular; - file->file_size = proc->output_size; - } - } - - irq_restore(irq); - return written; - } - - if (!proc_opened_files){ - kprint("No files open"); - return 0; - } - irq_flags_t irq = irq_save_disable(); - module_file *file = (module_file*)hash_map_get(proc_opened_files, &fd->id, sizeof(uint64_t)); - bool ro = file && file->read_only; - irq_restore(irq); - if (!file) return 0; - if (ro) return 0; - return 0; -} - -void close_proc(file *fd) { - if (!fd) return; - if (!proc_opened_files) return; - - uint64_t fid = fd->id; - process_t *reset_proc = 0; - irq_flags_t irq = irq_save_disable(); - module_file *mfile = (module_file*)hash_map_get(proc_opened_files, &fid, sizeof(fid)); - if (!mfile) { - irq_restore(irq); - return; - } - - procfs_owner *owner_info = (procfs_owner*)mfile->private_data; - process_t *owner = 0; - if (owner_info && owner_info->proc && owner_info->proc->id == owner_info->pid) owner = owner_info->proc; - if (owner) { - if (owner->procfs_refs) owner->procfs_refs--; - if (process_can_reset(owner) && process_has_runtime_state(owner)) reset_proc = owner; - } - - if (mfile->references > 0) mfile->references--; - if (mfile->references == 0) { - void *owned = mfile->file_buffer.buffer; - buffer_options options = mfile->file_buffer.options; - bool owned_postmortem = owner && owned == (void*)owner->postmortem_output; - hash_map_remove(proc_opened_files, &fid, sizeof(fid), 0); - irq_restore(irq); - if (owned && options == buffer_opt_none && !(reset_proc && owned_postmortem)) { - release(owned); - if (owned_postmortem) { - owner->postmortem_output = 0; - owner->postmortem_output_size = 0; - } - } - if (mfile->private_data) release(mfile->private_data); - release(mfile); - if (reset_proc) reset_process(reset_proc); - return; - } - irq_restore(irq); +void schedule_thread(process_t *proc, thread_t *t){ + enqueue_ready_thread(t); +} + +thread_t* new_thread(process_t *proc, thread_t *addr, u64 spsr, uptr entry_point){ + if (addr != &proc->main_thread) spsr = proc->spsr; + else proc->spsr = spsr; + stack_t stack = new_stack(proc); + if (!proc || !stack.top || !stack.size || !addr) return 0; + *addr = (thread_t){ + .pc = entry_point, + .pid = proc->id, + .regs = {}, + .sp = stack.top, + .stack_info = stack, + .spsr = spsr, + .tid = ++proc->thread_ids + // .state = BLOCKED, + }; + addr->regs[30] = is_privileged(proc) ? (uptr)kernel_thread_return_trampoline : proc->shared_page+sizeof(u32); + return addr; +} + +bool load_process_module(process_t *p, system_module *m, bool global){//TODO: this doesn't belong here + if (!p->permissions.owned_fs_id) p->permissions.owned_fs_id = register_fs_id(); + module_root *root = get_fs_for_id(p->permissions.fs_id); + system_module *mod = zalloc(sizeof(system_module)); + memcpy(mod, m, sizeof(system_module)); + mod->name = string_from_literal(m->name).data; + mod->mount = string_from_literal(m->mount).data; + mod->owner = p->id; + bool ret = load_module_to(root, mod); + if (!ret) return false; + if (!global) return true; + return load_module(mod); } - -system_module scheduler_module = (system_module){ - .name = "scheduler", - .mount = "proc", - .version = VERSION_NUM(0, 1, 0, 1), - .init = init_scheduler_module, - .fini = 0, - .open = open_proc, - .read = read_proc, - .write = write_proc, - .close = close_proc, - .getstat = stat_proc, - .readdir = readdir_proc, -}; diff --git a/kernel/process/scheduler.h b/kernel/process/scheduler.h index 544eb930..01d7f99e 100644 --- a/kernel/process/scheduler.h +++ b/kernel/process/scheduler.h @@ -3,6 +3,7 @@ #include "types.h" #include "process/process.h" #include "files/system_module.h" +#include "procfs.h" typedef enum { INTERRUPT, @@ -27,7 +28,9 @@ void save_return_address_interrupt(); void init_main_process(); process_t* init_process(); void ready_process(process_t *proc); +void ready_thread(thread_t *t); void save_syscall_return(uint64_t value); +void prepare_process_restore(process_t *proc); void process_restore(); void stop_process(uint16_t pid, int32_t exit_code); @@ -39,15 +42,15 @@ void resume_blocked_process(process_t *proc); void name_process(process_t *proc, const char *name); -void sleep_process(uint64_t msec); +void sleep_thread(uint64_t msec); void wake_processes(); -void wake_process(process_t *proc); -bool load_process_module(process_t *p, system_module *m); +bool load_process_module(process_t *p, system_module *m, bool global); process_t* get_current_proc(); process_t* get_kernel_proc(); process_t* get_idle_proc(); +thread_t* get_current_thread(); bool scheduler_in_idle(); process_t* get_proc_by_pid(uint16_t pid); uint16_t get_current_proc_pid(); @@ -61,6 +64,12 @@ bool get_current_privilege(); uint16_t process_count(); process_t *get_all_processes(); -extern system_module scheduler_module; +thread_t* alloc_thread(); +thread_t* new_thread(process_t *proc, thread_t *addr, u64 spsr, uptr entry_point); +void schedule_thread(process_t *proc, thread_t *t); + +thread_t* get_thread_from_proc(process_t *proc, u16 tid); + +bool init_scheduler(); extern char ksp[]; diff --git a/kernel/process/signals/signals.c b/kernel/process/signals/signals.c index f686f1f6..e42b54db 100644 --- a/kernel/process/signals/signals.c +++ b/kernel/process/signals/signals.c @@ -5,7 +5,7 @@ #include "console/kio.h" bool register_signal_handler(process_t *proc, signal_types type, signal_handler handler){ - if (proc->signal_handlers[type]){ + if (proc->signal_handlers[type].pc){ kprint("Signal already exists"); return false; } @@ -14,8 +14,7 @@ bool register_signal_handler(process_t *proc, signal_types type, signal_handler return false; } kprint("Signal handler added"); - proc->signal_handlers[type] = handler; - //TODO: Can we check if the handler is in proc's va? cba rn + new_thread(proc, &proc->signal_handlers[type], proc->main_thread.spsr, (uptr)handler); return true; } @@ -31,19 +30,15 @@ bool send_signal_proc_proc(signal_types type, i64 value, process_t *source, proc return true; } - signal_buffer_t *buffer = &destination->signal_buffer; - - uint32_t next_index = (buffer->write_index + 1) % INPUT_BUFFER_CAPACITY; - - buffer->entries[buffer->write_index] = (signal_info_t){ - .sender = source->id, - .type = type, - .value = value, - }; - buffer->write_index = next_index; - - if (buffer->write_index == buffer->read_index) - buffer->read_index = (buffer->read_index + 1) % INPUT_BUFFER_CAPACITY; + thread_t *t = &destination->signal_handlers[type]; + if (t->pc) + schedule_thread(destination,t); + else + handle_signal_default(destination, &(signal_info_t){ + .sender = source->id, + .type = type, + .value = value, + }); switch_proc(YIELD); diff --git a/kernel/process/signals/signals.h b/kernel/process/signals/signals.h index 6e965554..aad0d3e8 100644 --- a/kernel/process/signals/signals.h +++ b/kernel/process/signals/signals.h @@ -2,7 +2,7 @@ #include "signals/signal_types.h" -typedef struct process process_t; +typedef struct process_t process_t; extern process_t* get_proc_by_pid(uint16_t pid); bool register_signal_handler(process_t* proc, signal_types type, signal_handler handler); diff --git a/kernel/process/stack_manager.c b/kernel/process/stack_manager.c new file mode 100644 index 00000000..aed049a5 --- /dev/null +++ b/kernel/process/stack_manager.c @@ -0,0 +1,43 @@ +#include "stack_manager.h" +#include "exceptions/exception_handler.h" +#include "memory/mmu.h" + +uptr next_stack_addr(process_t *proc){ + if (is_privileged(proc)) return 0; + for (uptr start = stack_max_addr; start > stack_min_addr; start -= stack_max + PAGE_SIZE){ + vma *m = mm_find_vma(&proc->mm, start-stack_max); + if (!m){ + return start; + } + } + print("Damn girl how many stacks u got"); + return 0; +} + +void unmap_stack(process_t *proc, stack_t stack){ + vma *m = mm_find_vma(&proc->mm, stack.top-stack_max); + if (m){ + for (uptr addr = stack.top-stack.size; addr < stack.top; addr += PAGE_SIZE){ + uptr pa = 0; + mmu_unmap_and_get_pa(proc->mm.ttbr0, addr, &pa); + if (pa) + pfree((void*)pa, PAGE_SIZE); + } + mm_remove_vma(&proc->mm, stack.top-stack.size, stack.top); + } +} + +stack_t new_stack(process_t *proc){ + uptr stack_top = 0; + if (is_privileged(proc)) { + void *st = palloc(stack_max, MEM_PRIV_KERNEL, MEM_RW, true); + stack_top = (uptr)st + stack_max; + register_allocation(proc->alloc_map, st, stack_max); + } else stack_top = next_stack_addr(proc); + if (!stack_top) return (stack_t){}; + uptr stack_limit = stack_top - stack_max; + print("New stack at %llx-%llx",stack_limit,stack_top); + if (!is_privileged(proc) && !mm_add_vma(&proc->mm, stack_limit, stack_top, MEM_RW, VMA_KIND_STACK, VMA_FLAG_DEMAND)) + return (stack_t){}; + return (stack_t){.top = stack_top, .size = stack_max, .max = stack_max}; +} \ No newline at end of file diff --git a/kernel/process/stack_manager.h b/kernel/process/stack_manager.h new file mode 100644 index 00000000..96e7883c --- /dev/null +++ b/kernel/process/stack_manager.h @@ -0,0 +1,12 @@ +#pragma once + +#include "types.h" +#include "process.h" + +#define stack_max 0x100000 +#define stack_max_addr 0x7ffffffff000ULL +#define stack_distance (stack_max + PAGE_SIZE) +#define stack_min_addr 0x100000000000ULL + +stack_t new_stack(process_t *proc); +void unmap_stack(process_t *proc, stack_t stack); \ No newline at end of file diff --git a/kernel/process/syscall.c b/kernel/process/syscall.c index 14f37a0e..87739089 100644 --- a/kernel/process/syscall.c +++ b/kernel/process/syscall.c @@ -34,30 +34,32 @@ #include "filesystem/modules/fs_isolation.h" #include "files/dir_list.h" #include "theme/theme.h" +#include "jobs/job_manager.h" +#include "stack_manager.h" int syscall_depth = 0; uintptr_t cpec; #define SYSCALL_STR(name, arg, write)\ - if (!ctx->arg) return 0;\ - char *name = (char*)ctx->arg;\ - if (!validate_address(ctx, ctx->arg, sizeof(name), write)) return 0; + char *name = (char*)current_thread->arg;\ + if (!name) return 0;\ + if (!validate_address(ctx, current_thread, (uptr)name, sizeof(name), write)) return 0; #define SYSCALL_ARG(type, name, arg, write) \ - if (!ctx->arg) return 0;\ - type *name = (type*)ctx->arg;\ - if (!validate_address(ctx, (uptr)name, sizeof(type), write)) return 0;\ + type *name = (type*)current_thread->arg;\ + if (!name) return 0;\ + if (!validate_address(ctx, current_thread, (uptr)name, sizeof(type), write)) return 0;\ #define SYSCALL_ARG_SIZE(type, name, size, arg, write) \ - if (!ctx->arg && size) return 0;\ - type *name = (type*)ctx->arg;\ - if (!validate_address(ctx, (uptr)name, size, write)) return 0;\ + type *name = (type*)current_thread->arg;\ + if (!name && size) return 0;\ + if (!validate_address(ctx, current_thread, (uptr)name, size, write)) return 0;\ //TEST: What happens if we pass another process' data in here? -typedef uint64_t (*syscall_entry)(process_t *ctx); +typedef uint64_t (*syscall_entry)(process_t *ctx, thread_t *current_thread); -uptr syscall_palloc(process_t *ctx){ - size_t size = ctx->PROC_X0; +uptr syscall_palloc(process_t *ctx, thread_t *current_thread){ + size_t size = current_thread->PROC_X0; if(!size) return 0; u64 pages = count_pages(size, PAGE_SIZE); size_t alloc_size = pages * PAGE_SIZE; @@ -77,8 +79,8 @@ uptr syscall_palloc(process_t *ctx){ return (uptr)kva; } -u64 syscall_pfree(process_t *ctx){ - uptr va = ctx->PROC_X0; +u64 syscall_pfree(process_t *ctx, thread_t *current_thread){ + uptr va = current_thread->PROC_X0; if (!va) return 0; if (ctx->mm.ttbr0) { @@ -111,35 +113,35 @@ u64 syscall_pfree(process_t *ctx){ return 0; } -u64 syscall_printl(process_t *ctx){ +u64 syscall_printl(process_t *ctx, thread_t *current_thread){ SYSCALL_STR(str, PROC_X0, false); kprint((char*)str); return 0; } -u64 syscall_serial_transmit(process_t *ctx){//TODO: will probably require special permission +u64 syscall_serial_transmit(process_t *ctx, thread_t *current_thread){//TODO: will probably require special permission if (sys_get_focused_pid() != ctx->id) return 0; - u8 byte = ctx->PROC_X0; + u8 byte = current_thread->PROC_X0; if (byte) uart_raw_putc(byte); return 0; } -u64 syscall_read_key(process_t *ctx){ +u64 syscall_read_key(process_t *ctx, thread_t *current_thread){ SYSCALL_ARG(keypress, key, PROC_X0, true); return sys_read_input_current(key); } -u64 syscall_read_event(process_t *ctx){ +u64 syscall_read_event(process_t *ctx, thread_t *current_thread){ SYSCALL_ARG(kbd_event, ev, PROC_X0, true); return sys_read_event_current(ev); } -u64 syscall_read_shortcut(process_t *ctx){ +u64 syscall_read_shortcut(process_t *ctx, thread_t *current_thread){ kprint("[SYSCALL implementation error] Shortcut syscalls are not implemented yet"); return 0; } -u64 syscall_get_mouse(process_t *ctx){ +u64 syscall_get_mouse(process_t *ctx, thread_t *current_thread){ //TODO: we're not fully preventing the mouse from being read outside of proc's window (raw & buttons) if (sys_get_focused_pid() != ctx->id) return 0; SYSCALL_ARG(mouse_data, inp, PROC_X0, true); @@ -149,22 +151,22 @@ u64 syscall_get_mouse(process_t *ctx){ return 0; } -uptr syscall_gpu_request_ctx(process_t *ctx){ +uptr syscall_gpu_request_ctx(process_t *ctx, thread_t *current_thread){ SYSCALL_ARG(draw_ctx, win, PROC_X0, true); get_window_ctx(win); return 0; } -u64 syscall_gpu_flush(process_t *ctx){ +u64 syscall_gpu_flush(process_t *ctx, thread_t *current_thread){ SYSCALL_ARG(draw_ctx, win, PROC_X0, true); commit_frame(win, 0, false); gpu_flush(); return 0; } -u64 syscall_gpu_resize_ctx(process_t *ctx){ - uint32_t width = (uint32_t)ctx->PROC_X1; - uint32_t height = (uint32_t)ctx->PROC_X2; +u64 syscall_gpu_resize_ctx(process_t *ctx, thread_t *current_thread){ + uint32_t width = (uint32_t)current_thread->PROC_X1; + uint32_t height = (uint32_t)current_thread->PROC_X2; resize_window(width, height); SYSCALL_ARG(draw_ctx, win, PROC_X0, true); get_window_ctx(win); @@ -172,35 +174,51 @@ u64 syscall_gpu_resize_ctx(process_t *ctx){ return 0; } -u64 syscall_char_size(process_t *ctx){ - return gpu_get_char_size(ctx->PROC_X0); +u64 syscall_char_size(process_t *ctx, thread_t *current_thread){ + return gpu_get_char_size(current_thread->PROC_X0); } -u64 syscall_msleep(process_t *ctx){ +u64 syscall_msleep(process_t *ctx, thread_t *current_thread){ syscall_depth--; - sleep_process(ctx->PROC_X0); + sleep_thread(current_thread->PROC_X0); return 0; } -u64 syscall_halt(process_t *ctx){ - kprintf("Process has ended with code %i",ctx->PROC_X0); +u64 syscall_halt(process_t *ctx, thread_t *current_thread){ + kprintf("Process has ended with code %i",current_thread->PROC_X0); syscall_depth--; - stop_current_process(ctx->PROC_X0); + stop_current_process(current_thread->PROC_X0); return 0; } -u64 syscall_exec(process_t *ctx){ +u64 syscall_halt_thread(process_t *ctx, thread_t *current_thread){ + kprintf("Thread has ended with code %i",current_thread->PROC_X0); + syscall_depth--; + if (current_thread->job_id){ + fulfill_job(current_thread->job_id, current_thread->PROC_X0, current_thread); + } + if (current_thread == &ctx->main_thread) + stop_current_process(current_thread->PROC_X0); + else { + current_thread->state = STOPPED; + unmap_stack(ctx, current_thread->stack_info); + switch_proc(YIELD);//TODO: proper cleanup + } + return 0; +} + +u64 syscall_exec(process_t *ctx, thread_t *current_thread){ SYSCALL_STR(prog_name, PROC_X0, false); //TODO: prog-name *might* need to be resolved in fs if it contains / - int argc = (int)ctx->PROC_X1; - uintptr_t uargv = (uintptr_t)ctx->PROC_X2; - uint32_t mode = (uint32_t)ctx->PROC_X3; + int argc = (int)current_thread->PROC_X1; + uintptr_t uargv = (uintptr_t)current_thread->PROC_X2; + uint32_t mode = (uint32_t)current_thread->PROC_X3; if (argc < 0 || argc > 64) return 0; user_argv_t user_argv = {}; - uaccess_result_t ur = copy_argv_from_user(ctx, argc, uargv, &user_argv); + uaccess_result_t ur = copy_argv_from_user(ctx, current_thread, argc, uargv, &user_argv); if (ur != UACCESS_OK) return 0; process_t *p = execute(prog_name, argc, user_argv.argv, mode); @@ -208,43 +226,43 @@ u64 syscall_exec(process_t *ctx){ return p ? p->id : 0; } -u64 syscall_kill_process(process_t *ctx) { - uint16_t pid = (uint16_t)ctx->PROC_X0; +u64 syscall_kill_process(process_t *ctx, thread_t *current_thread) { + uint16_t pid = (uint16_t)current_thread->PROC_X0; if (!pid) return 0; process_t *target = get_proc_by_pid(pid); if (!target || target->state == STOPPED) return 0; if (target->id == 1) return 0; - if ((target->spsr & 0xF) != 0) return 0; + if (is_privileged(target)) return 0; if (!ctx->win_id || target->win_id != ctx->win_id) return 0; stop_process(pid, -9); return 0; } -u64 syscall_get_time(process_t *ctx){ +u64 syscall_get_time(process_t *ctx, thread_t *current_thread){ return timer_now_msec(); } -u64 syscall_socket_create(process_t *ctx){ - Socket_Role role = (Socket_Role)ctx->PROC_X0; - protocol_t protocol = (protocol_t)ctx->PROC_X1; +u64 syscall_socket_create(process_t *ctx, thread_t *current_thread){ + Socket_Role role = (Socket_Role)current_thread->PROC_X0; + protocol_t protocol = (protocol_t)current_thread->PROC_X1; SYSCALL_ARG(const SocketExtraOptions, extra, PROC_X2, false); SYSCALL_ARG(SocketHandle, out, PROC_X3, true); return create_socket(role, protocol, extra, ctx->id, out); } -u64 syscall_socket_bind(process_t *ctx){ +u64 syscall_socket_bind(process_t *ctx, thread_t *current_thread){ SYSCALL_ARG(SocketHandle,handle,PROC_X0, true); - ip_version_t ip_version = (ip_version_t)ctx->PROC_X1; - uint16_t port = (uint16_t)ctx->PROC_X2; + ip_version_t ip_version = (ip_version_t)current_thread->PROC_X1; + uint16_t port = (uint16_t)current_thread->PROC_X2; return bind_socket(handle, port, ip_version, ctx->id); } -u64 syscall_socket_connect(process_t *ctx){ - uint8_t dst_kind = (uint8_t)ctx->PROC_X1; - uint16_t port = (uint16_t)ctx->PROC_X3; +u64 syscall_socket_connect(process_t *ctx, thread_t *current_thread){ + uint8_t dst_kind = (uint8_t)current_thread->PROC_X1; + uint16_t port = (uint16_t)current_thread->PROC_X3; SYSCALL_ARG(SocketHandle,handle,PROC_X0,true); @@ -263,23 +281,23 @@ u64 syscall_socket_connect(process_t *ctx){ return connect_socket(handle, dst_kind, dst, port, ctx->id); } -u64 syscall_socket_listen(process_t *ctx){ +u64 syscall_socket_listen(process_t *ctx, thread_t *current_thread){ SYSCALL_ARG(SocketHandle,handle, PROC_X0, true); - int32_t backlog = (int32_t)ctx->PROC_X1; + int32_t backlog = (int32_t)current_thread->PROC_X1; return listen_on(handle, backlog, ctx->id); } -u64 syscall_socket_accept(process_t *ctx){ +u64 syscall_socket_accept(process_t *ctx, thread_t *current_thread){ SYSCALL_ARG(SocketHandle,handle, PROC_X0, true); accept_on_socket(handle, ctx->id); return 1; } -u64 syscall_socket_send(process_t *ctx){ - uint8_t dst_kind = (uint8_t)ctx->PROC_X1; - uint16_t port = (uint16_t)ctx->PROC_X3; - size_t size = (size_t)ctx->regs[5]; +u64 syscall_socket_send(process_t *ctx, thread_t *current_thread){ + uint8_t dst_kind = (uint8_t)current_thread->PROC_X1; + uint16_t port = (uint16_t)current_thread->PROC_X3; + size_t size = (size_t)current_thread->regs[5]; SYSCALL_ARG(SocketHandle,handle, PROC_X0, true); @@ -305,8 +323,8 @@ u64 syscall_socket_send(process_t *ctx){ return send_on_socket(handle, dst_kind, dst, port, kbuf, size, ctx->id); } -u64 syscall_socket_receive(process_t *ctx){ - size_t size = (size_t)ctx->PROC_X2; +u64 syscall_socket_receive(process_t *ctx, thread_t *current_thread){ + size_t size = (size_t)current_thread->PROC_X2; if (!size) return 0; uint64_t alloc_size = (size + 0xFFF) & ~0xFFFULL; @@ -317,7 +335,7 @@ u64 syscall_socket_receive(process_t *ctx){ return receive_from_socket(handle, buf, size, src, ctx->id); } -u64 syscall_socket_close(process_t *ctx){ +u64 syscall_socket_close(process_t *ctx, thread_t *current_thread){ SYSCALL_ARG(SocketHandle,handle, PROC_X0, true); return close_socket(handle, ctx->id); } @@ -325,13 +343,13 @@ u64 syscall_socket_close(process_t *ctx){ #define ISOLATEDFS #define ISOLATEDFS_ALLOW_KFS true -u64 syscall_openf(process_t *ctx){ +u64 syscall_openf(process_t *ctx, thread_t *current_thread){ #ifdef ISOLATEDFS SYSCALL_STR(path, PROC_X0, false); SYSCALL_ARG(file,descriptor,PROC_X1, true); module_root rootfs = {}; string s = resolve_isolated_path(path, ctx->permissions.fs_id, &rootfs, ISOLATEDFS_ALLOW_KFS); - if (!s.data || !s.length) return 0; + if (!s.data || !s.length || !rootfs.map) return 0; FS_RESULT res = open_file(&rootfs, s.data, descriptor); string_free(s); return res; @@ -347,23 +365,23 @@ u64 syscall_openf(process_t *ctx){ #endif } -u64 syscall_readf(process_t *ctx){ +u64 syscall_readf(process_t *ctx, thread_t *current_thread){ SYSCALL_ARG(file, descriptor, PROC_X0, true); - size_t size = (size_t)ctx->PROC_X2; + size_t size = (size_t)current_thread->PROC_X2; SYSCALL_ARG_SIZE(void, buf, size, PROC_X1, true); return read_file(descriptor, buf, size); } -u64 syscall_writef(process_t *ctx){ +u64 syscall_writef(process_t *ctx, thread_t *current_thread){ SYSCALL_ARG(file, descriptor, PROC_X0, true); - size_t size = (size_t)ctx->PROC_X2; + size_t size = (size_t)current_thread->PROC_X2; SYSCALL_ARG_SIZE(void, buf, size, PROC_X1, false); return write_file(descriptor, buf, size); } -u64 syscall_sreadf(process_t *ctx){ +u64 syscall_sreadf(process_t *ctx, thread_t *current_thread){ SYSCALL_STR(path, PROC_X0, false); - size_t size = (size_t)ctx->PROC_X2; + size_t size = (size_t)current_thread->PROC_X2; SYSCALL_ARG_SIZE(void, buf, size, PROC_X1, false); #ifdef ISOLATEDFS module_root rootfs = {}; @@ -377,11 +395,11 @@ u64 syscall_sreadf(process_t *ctx){ #endif } -u64 syscall_swritef(process_t *ctx){ +u64 syscall_swritef(process_t *ctx, thread_t *current_thread){ SYSCALL_STR(path, PROC_X0, false); - size_t size = (size_t)ctx->PROC_X2; + size_t size = (size_t)current_thread->PROC_X2; SYSCALL_ARG_SIZE(void, buf, size, PROC_X1, false); - bool append = (bool)ctx->PROC_X3; + bool append = (bool)current_thread->PROC_X3; #ifdef ISOLATEDFS module_root rootfs = {}; string s = resolve_isolated_path(path, ctx->permissions.fs_id, &rootfs, ISOLATEDFS_ALLOW_KFS); @@ -394,28 +412,32 @@ u64 syscall_swritef(process_t *ctx){ #endif } -u64 syscall_closef(process_t *ctx){ +u64 syscall_closef(process_t *ctx, thread_t *current_thread){ SYSCALL_ARG(file,descriptor, PROC_X0, true); close_file(descriptor); return 0; } -u64 syscall_dir_list(process_t *ctx){ +u64 syscall_dir_list(process_t *ctx, thread_t *current_thread){ SYSCALL_STR(path,PROC_X0, false); - size_t size = (size_t)ctx->PROC_X2; + size_t size = (size_t)current_thread->PROC_X2; SYSCALL_ARG_SIZE(void, buf, size, PROC_X1, true); SYSCALL_ARG(u64,offset,PROC_X3, true); #ifdef ISOLATEDFS module_root rootfs = {}; string s = resolve_isolated_path(path, ctx->permissions.fs_id, &rootfs, ISOLATEDFS_ALLOW_KFS); + if (!rootfs.map) return 0; if (!s.data || !s.length || strncmp(s.data,"/",s.length) == 0){ size_t ret = 0; fs_dir_list_helper helper = create_dir_list_helper(buf, size); - if (rootfs.buckets != kernel_fs()->buckets){ + if (rootfs.map->buckets != kernel_fs()->map->buckets){ ret += list_root_from(&rootfs, &helper, offset); } if (ret >= size) return ret; + //TODO: this calculation needs to make the offsets relative for each root mod +#if ISOLATEDFS_ALLOW_KFS ret += list_root_from(kernel_fs(), &helper, offset); +#endif return ret; } size_t ret = list_directory_contents(&rootfs, s.data, buf, size, offset); @@ -426,7 +448,7 @@ u64 syscall_dir_list(process_t *ctx){ #endif } -u64 syscall_stat(process_t *ctx){ +u64 syscall_stat(process_t *ctx, thread_t *current_thread){ SYSCALL_STR(path,PROC_X0, false); SYSCALL_ARG(fs_stat,out_stat,PROC_X1, true); #ifdef ISOLATEDFS @@ -443,39 +465,39 @@ u64 syscall_stat(process_t *ctx){ #endif } -u64 syscall_trunc(process_t* ctx){ +u64 syscall_trunc(process_t* ctx, thread_t *current_thread){ SYSCALL_ARG(file,descriptor,PROC_X0, true); - size_t size = ctx->PROC_X1; + size_t size = current_thread->PROC_X1; return truncate(descriptor, size); } -u64 syscall_signal_send(process_t* ctx){ - signal_types type = ctx->PROC_X0; - u16 proc_id = ctx->PROC_X1; +u64 syscall_signal_send(process_t* ctx, thread_t *current_thread){ + signal_types type = current_thread->PROC_X0; + u16 proc_id = current_thread->PROC_X1; return send_signal_proc_id(type, 0, ctx, proc_id); } -u64 syscall_signal_handler(process_t* ctx){ - kprint("[SYSCALL implementation error] syscall handlers are not supported in userspace yet"); - //TODO: for this and FS modules, we'll need to set up an isolated environment (thread-like) for them to run in - return 0; - signal_types type = ctx->PROC_X0; - uptr handler = ctx->PROC_X1; +u64 syscall_signal_handler(process_t* ctx, thread_t *current_thread){ + signal_types type = current_thread->PROC_X0; + uptr handler = current_thread->PROC_X1; + if (!handler) return 0; - if (!validate_address(ctx, handler, sizeof(uptr), false)) return 0; + if (!validate_address(ctx, current_thread, handler, sizeof(uptr), false)) return 0; return register_signal_handler(ctx, type, (signal_handler)handler); } -// uint64_t syscall_load_fsmod(process_t *ctx){ -// system_module *mod = (system_module*)ctx->PROC_X0; -// return load_process_module(ctx,mod); -// } +uint64_t syscall_load_fsmod(process_t *ctx, thread_t *current_thread){ + SYSCALL_ARG(system_module,mod,PROC_X0, false); + bool global = current_thread->PROC_X1; + return load_process_module(ctx,mod,global); +} -// uint64_t syscall_unload_fsmod(process_t *ctx){ -// return unload_module(&ctx->exposed_fs); -// } +uint64_t syscall_unload_fsmod(process_t *ctx, thread_t *current_thread){ + //TODO: this syscall needs to be remade with the specific module + return 0; +} -u64 syscall_in_case_of_js(process_t *ctx){ +u64 syscall_in_case_of_js(process_t *ctx, thread_t *current_thread){ panic("Shame on you\r\n\ Don't ever do that again\r\n\ ....................../'¯/) \r\n\ @@ -506,6 +528,7 @@ syscall_entry syscalls[] = { [RESIZE_DRAW_CTX_CODE] = syscall_gpu_resize_ctx, [SLEEP_CODE] = syscall_msleep, [HALT_CODE] = syscall_halt, + [HALT_THREAD_CODE] = syscall_halt_thread, [EXEC_CODE] = syscall_exec, [KILL_PROCESS_CODE] = syscall_kill_process, [GET_TIME_CODE] = syscall_get_time, @@ -526,8 +549,8 @@ syscall_entry syscalls[] = { [DIR_LIST_CODE] = syscall_dir_list, [FILE_STAT_CODE] = syscall_stat, [FILE_TRNC_CODE] = syscall_trunc, - // [LOAD_FSMODULE_CODE] = syscall_load_fsmod, - // [UNLOAD_FSMODULE_CODE] = syscall_unload_fsmod, + [LOAD_FSMODULE_CODE] = syscall_load_fsmod, + [UNLOAD_FSMODULE_CODE] = syscall_unload_fsmod, [SIGNAL_SEND_CODE] = syscall_signal_send, [SIGNAL_HANDLER_CODE] = syscall_signal_handler, @@ -618,7 +641,6 @@ void coredump(uintptr_t esr, uintptr_t elr, uintptr_t far, uintptr_t sp){ void sync_el0_handler_c(){ save_return_address_interrupt(); - mmu_ttbr0_disable_user(); syscall_depth++; #if TEST @@ -626,6 +648,7 @@ void sync_el0_handler_c(){ #endif process_t *proc = get_current_proc(); + thread_t *current_thread = (thread_t*)cpec; uint64_t elr; asm volatile ("mrs %0, elr_el1" : "=r"(elr)); @@ -643,7 +666,7 @@ void sync_el0_handler_c(){ uint64_t far; asm volatile ("mrs %0, far_el1" : "=r"(far)); if (ec == 0x24 || ec == 0x20){ - if (mm_try_handle_page_fault(proc, far, esr)){ + if (mm_try_handle_page_fault(proc, current_thread, far, esr)){ syscall_depth--; process_restore(); } @@ -653,32 +676,37 @@ void sync_el0_handler_c(){ if (ec == 0x15) { syscall_entry entry = syscalls[iss]; if (entry){ - result = entry(proc); + result = entry(proc, current_thread); } else { kprintf("Unknown syscall in process. ESR: %llx. ELR: %llx. FAR: %llx", esr, elr, far); - coredump(esr, elr, far, proc->sp); + coredump(esr, elr, far, current_thread->sp); syscall_depth--; stop_current_process(ec); } } else { if (currentEL == 1){ - if (syscall_depth < 3){ - kprintf("System has crashed. ESR: %llx. ELR: %llx. FAR: %llx", esr, elr, far); - uint64_t ksp = 0; - asm volatile ("mov %0, sp" : "=r"(ksp)); - coredump(esr, elr, far, ksp); - } - handle_exception("UNEXPECTED EXCEPTION", ec); - while (true); + if (syscall_depth < 3){ + uint64_t ksp = 0; + asm volatile ("mov %0, sp" : "=r"(ksp)); + kprintf("System has crashed. ESR: %llx. ELR: %llx. FAR: %llx. KSP: %llx", esr, elr, far, ksp); + coredump(esr, elr, far, ksp); + } + handle_exception("UNEXPECTED EXCEPTION", ec); + while (true); } else { - kprintf("Process has crashed. ESR: %llx. ELR: %llx. FAR: %llx. SP: %llx", esr, elr, far, proc->sp); - if (syscall_depth <= 2) coredump(esr, elr, far, proc->sp); + kprintf("Process [p: %i t: %i] has crashed. ESR: %llx. ELR: %llx. FAR: %llx. SP: %llx", current_thread->pid,current_thread->tid, esr, elr, far, current_thread->sp); + coredump(esr, elr, far, current_thread->sp); syscall_depth--; stop_current_process(ec); } } syscall_depth--; save_syscall_return(result); + // print("Return to %i",current_thread->pid); + if (current_thread->kstack_top) { + //TODO: schedule kstack_top to cleanup, but don't do immediately as we're in it + current_thread->kstack_top = 0; + } process_restore(); } diff --git a/kernel/process/uaccess.c b/kernel/process/uaccess.c index 6705f0e9..726dfd5c 100644 --- a/kernel/process/uaccess.c +++ b/kernel/process/uaccess.c @@ -5,7 +5,7 @@ #include "std/memory.h" #include "alloc/allocate.h" -bool access_ok_range(process_t *proc, uintptr_t addr, size_t size, bool want_write) { +bool access_ok_range(process_t *proc, thread_t *current_thread, uintptr_t addr, size_t size, bool want_write) { if (!proc) return false; if (!proc->mm.ttbr0) return false; if (!size) return true; @@ -30,10 +30,10 @@ bool access_ok_range(process_t *proc, uintptr_t addr, size_t size, bool want_wri return true; } -uaccess_result_t copy_from_user(process_t *proc, void *dst, uintptr_t src, size_t size) { +uaccess_result_t copy_from_user(process_t *proc, thread_t *current_thread, void *dst, uintptr_t src, size_t size) { if (!dst && size) return UACCESS_EINVAL; if (!size) return UACCESS_OK; - if (!access_ok_range(proc, src, size, false)) return UACCESS_EFAULT; + if (!access_ok_range(proc, current_thread, src, size, false)) return UACCESS_EFAULT; uint8_t *d = (uint8_t*)dst; @@ -46,7 +46,7 @@ uaccess_result_t copy_from_user(process_t *proc, void *dst, uintptr_t src, size_ uintptr_t pa =mmu_translate((uint64_t*)proc->mm.ttbr0, src, &st); if (st) { uint64_t esr = (0x24ULL << 26) | 0x7ULL; - if (!mm_try_handle_page_fault(proc, src, esr)) return UACCESS_EFAULT; + if (!mm_try_handle_page_fault(proc, current_thread, src, esr)) return UACCESS_EFAULT; pa = mmu_translate((uint64_t*)proc->mm.ttbr0, src, &st); if (st) return UACCESS_EFAULT; @@ -61,10 +61,10 @@ uaccess_result_t copy_from_user(process_t *proc, void *dst, uintptr_t src, size_ return UACCESS_OK; } -bool validate_address(process_t *proc, uintptr_t addr, size_t size, bool want_write) { +bool validate_address(process_t *proc, thread_t *current_thread, uintptr_t addr, size_t size, bool want_write) { if (!addr && size) return false; if (!size) return true; - if (!access_ok_range(proc, addr, size, want_write)) return false; + if (!access_ok_range(proc, current_thread, addr, size, want_write)) return false; while (size) { size_t off = addr & (PAGE_SIZE - 1); @@ -75,7 +75,7 @@ bool validate_address(process_t *proc, uintptr_t addr, size_t size, bool want_wr mmu_translate((uint64_t*)proc->mm.ttbr0, addr, &st); if (st) { uint64_t esr = (0x24ULL << 26) | 0x7ULL | (want_write << 6); - if (!mm_try_handle_page_fault(proc, addr, esr)) return false; + if (!mm_try_handle_page_fault(proc, current_thread, addr, esr)) return false; mmu_translate((uint64_t*)proc->mm.ttbr0, addr, &st); if (st) return false; @@ -88,10 +88,10 @@ bool validate_address(process_t *proc, uintptr_t addr, size_t size, bool want_wr return true; } -uaccess_result_t copy_to_user(process_t *proc, uintptr_t dst, const void *src, size_t size) { +uaccess_result_t copy_to_user(process_t *proc, thread_t *current_thread, uintptr_t dst, const void *src, size_t size) { if (!src && size) return UACCESS_EINVAL; if (!size) return UACCESS_OK; - if (!access_ok_range(proc, dst, size, true)) return UACCESS_EFAULT; + if (!access_ok_range(proc, current_thread, dst, size, true)) return UACCESS_EFAULT; const uint8_t *s = (const uint8_t*)src; @@ -104,7 +104,7 @@ uaccess_result_t copy_to_user(process_t *proc, uintptr_t dst, const void *src, s uintptr_t pa = mmu_translate((uint64_t*)proc->mm.ttbr0, dst, &st); if (st) { uint64_t esr = (0x24ULL << 26) | 0x7ULL | (1 << 6); - if (!mm_try_handle_page_fault(proc, dst, esr)) return UACCESS_EFAULT; + if (!mm_try_handle_page_fault(proc, current_thread, dst, esr)) return UACCESS_EFAULT; pa = mmu_translate((uint64_t*)proc->mm.ttbr0, dst, &st); if (st) return UACCESS_EFAULT; @@ -119,7 +119,7 @@ uaccess_result_t copy_to_user(process_t *proc, uintptr_t dst, const void *src, s return UACCESS_OK; } -uaccess_result_t copy_str_from_user(process_t *proc, char *dst, size_t dst_size, uintptr_t src, size_t *out_copied, bool *out_terminated) { +uaccess_result_t copy_str_from_user(process_t *proc, thread_t *current_thread, char *dst, size_t dst_size, uintptr_t src, size_t *out_copied, bool *out_terminated) { if (out_copied) *out_copied = 0; if (out_terminated) *out_terminated = false; if (!dst || !dst_size) return UACCESS_EINVAL; @@ -131,12 +131,12 @@ uaccess_result_t copy_str_from_user(process_t *proc, char *dst, size_t dst_size, while (pos + 1 < dst_size) { size_t chunk = PAGE_SIZE - ((src + pos) & (PAGE_SIZE - 1)); if (chunk > dst_size - 1 - pos) chunk = dst_size - 1 - pos; - if (!access_ok_range(proc, src + pos, chunk, false)) return UACCESS_EFAULT; + if (!access_ok_range(proc, current_thread, src + pos, chunk, false)) return UACCESS_EFAULT; int st = 0; uintptr_t pa = mmu_translate((uint64_t*)proc->mm.ttbr0, src + pos, &st); if (st) { - if (!mm_try_handle_page_fault(proc, src + pos, (0x24ULL << 26) | 0x7ULL)) return UACCESS_EFAULT; + if (!mm_try_handle_page_fault(proc, current_thread, src + pos, (0x24ULL << 26) | 0x7ULL)) return UACCESS_EFAULT; pa = mmu_translate((uint64_t*)proc->mm.ttbr0, src + pos, &st); if (st) return UACCESS_EFAULT; } @@ -156,7 +156,7 @@ uaccess_result_t copy_str_from_user(process_t *proc, char *dst, size_t dst_size, return UACCESS_ENAMETOOLONG; } -uaccess_result_t copy_argv_from_user(process_t *proc, int argc, uintptr_t uargv, user_argv_t *out) { +uaccess_result_t copy_argv_from_user(process_t *proc, thread_t *current_thread, int argc, uintptr_t uargv, user_argv_t *out) { if (!out) return UACCESS_EINVAL; if (argc < 0 || argc > UACCESS_MAX_ARGV) return UACCESS_EINVAL; @@ -165,7 +165,7 @@ uaccess_result_t copy_argv_from_user(process_t *proc, int argc, uintptr_t uargv, for (int i = 0; i < argc; i++) { uintptr_t up = 0; - uaccess_result_t ur = copy_from_user(proc, &up, uargv + ((uintptr_t)i * sizeof(uintptr_t)), sizeof(up)); + uaccess_result_t ur = copy_from_user(proc, current_thread, &up, uargv + ((uintptr_t)i * sizeof(uintptr_t)), sizeof(up)); if (ur != UACCESS_OK) { free_argv_from_user(out); return ur; @@ -178,7 +178,7 @@ uaccess_result_t copy_argv_from_user(process_t *proc, int argc, uintptr_t uargv, char tmp[256] = {}; size_t copied = 0; bool term = false; - ur = copy_str_from_user(proc, tmp, sizeof(tmp), up, &copied, &term); + ur = copy_str_from_user(proc, current_thread, tmp, sizeof(tmp), up, &copied, &term); if (ur != UACCESS_OK) { free_argv_from_user(out); return ur; diff --git a/kernel/process/uaccess.h b/kernel/process/uaccess.h index 598d6a8e..0b2c6090 100644 --- a/kernel/process/uaccess.h +++ b/kernel/process/uaccess.h @@ -21,10 +21,10 @@ typedef struct user_argv { uint64_t bufsz[UACCESS_MAX_ARGV]; } user_argv_t; -bool access_ok_range(process_t *proc, uintptr_t addr, size_t size, bool want_write); -bool validate_address(process_t *proc, uintptr_t addr, size_t size, bool want_write); -uaccess_result_t copy_from_user(process_t *proc, void *dst, uintptr_t src, size_t size); -uaccess_result_t copy_to_user(process_t *proc, uintptr_t dst, const void *src, size_t size); -uaccess_result_t copy_str_from_user(process_t *proc, char *dst, size_t dst_size, uintptr_t src, size_t *out_copied, bool *out_terminated); -uaccess_result_t copy_argv_from_user(process_t *proc, int argc, uintptr_t uargv, user_argv_t *out); +bool access_ok_range(process_t *proc, thread_t *current_thread, uintptr_t addr, size_t size, bool want_write); +bool validate_address(process_t *proc, thread_t *current_thread, uintptr_t addr, size_t size, bool want_write); +uaccess_result_t copy_from_user(process_t *proc, thread_t *current_thread, void *dst, uintptr_t src, size_t size); +uaccess_result_t copy_to_user(process_t *proc, thread_t *current_thread, uintptr_t dst, const void *src, size_t size); +uaccess_result_t copy_str_from_user(process_t *proc, thread_t *current_thread, char *dst, size_t dst_size, uintptr_t src, size_t *out_copied, bool *out_terminated); +uaccess_result_t copy_argv_from_user(process_t *proc, thread_t *current_thread, int argc, uintptr_t uargv, user_argv_t *out); void free_argv_from_user(user_argv_t *argv); diff --git a/kernel/theme/theme.c b/kernel/theme/theme.c index de3139b8..4cb7bc7f 100644 --- a/kernel/theme/theme.c +++ b/kernel/theme/theme.c @@ -31,6 +31,7 @@ system_theme_t system_theme = { .cursor_color_deselected = CURSOR_COLOR_DESELECTED, .cursor_color_selected = CURSOR_COLOR_SELECTED, .use_window_shadows = true, + .use_desktop_zoom = true, }; system_config_t system_config = { @@ -39,7 +40,7 @@ system_config_t system_config = { .system_name = SYSTEM_NAME, .app_directory = "boot", .use_net = false, - .preferred_screen_size = {1920,1080}, + .preferred_screen_size = { 1920,1080 }, .headless = false, .use_login = false, .use_windows = true, @@ -103,6 +104,7 @@ void parse_theme_kvp(string_slice key, string_slice value, void *context){ parse_toml(cursor_color_deselected, system_theme, parse_hex_u64); parse_toml(cursor_color_selected, system_theme, parse_hex_u64); parse_toml(use_window_shadows, system_theme, parse_int_u64); + parse_toml(use_desktop_zoom, system_theme, parse_int_u64); parse_toml_str(panic_text, system_config); parse_toml_str(system_name, system_config); @@ -158,8 +160,11 @@ bool load_theme(){ return true; } +extern void refresh_desktop_colors(); + size_t reload(file* fd, const char *buf, size_t size, file_offset offset){ load_theme(); + refresh_desktop_colors(); return 0; } diff --git a/kernel/theme/theme.h b/kernel/theme/theme.h index cf194cd8..2e866156 100644 --- a/kernel/theme/theme.h +++ b/kernel/theme/theme.h @@ -26,6 +26,7 @@ typedef struct { u32 cursor_color_deselected; u32 cursor_color_selected; bool use_window_shadows; + bool use_desktop_zoom; } system_theme_t; typedef struct { diff --git a/kernel/tools/monitor_processes.c b/kernel/tools/monitor_processes.c index d1c8cae1..24dee29a 100644 --- a/kernel/tools/monitor_processes.c +++ b/kernel/tools/monitor_processes.c @@ -41,14 +41,14 @@ uint64_t calc_heap(uintptr_t ptr){ char *procname; void print_process_info(){ - process_t *proc = get_all_processes(); + process_t *proc = get_all_processes();//TODO: awareness of threads while (proc){ if (proc->id != 0 && proc->state != STOPPED && (!procname || strcmp_case(procname,proc->name,true) == 0)){ print("Process %s [pid = %i | status = %s]",(uintptr_t)proc->name,proc->id,(uintptr_t)parse_proc_state(proc->state)); - print("Stack: %x (%x). SP: %x",proc->stack, proc->stack_size, proc->sp); + print("Stack: %x (%x). SP: %x",proc->main_thread.stack_info.top, proc->main_thread.stack_info.size, proc->main_thread.sp); print("Heap: %x (%x)",proc->mm.mmap_bottom, calc_heap(proc->heap_phys)); - print("Flags: %x", proc->spsr); - print("PC: %x",proc->pc); + print("Flags: %x", proc->main_thread.spsr); + print("PC: %x",proc->main_thread.pc); } proc = proc->process_next; } @@ -126,16 +126,16 @@ void draw_process_view(){ fb_draw_string(&ctx,name.data, xo, name_y, scale, system_theme.bg_color); fb_draw_string(&ctx,state.data, xo, state_y, scale, system_theme.bg_color); - string pc = string_from_hex(proc->pc); + string pc = string_from_hex(proc->main_thread.pc); fb_draw_string(&ctx,pc.data, xo, pc_y, scale, system_theme.bg_color); string_free(pc); - draw_memory("Stack", xo, stack_y, stack_width, stack_height, proc->stack - proc->sp, proc->stack_size ? proc->stack_size : 1); + draw_memory("Stack", xo, stack_y, stack_width, stack_height, proc->main_thread.stack_info.top - proc->main_thread.sp, proc->main_thread.stack_info.size ? proc->main_thread.stack_info.size : 1); uint64_t heap = proc->mm.ttbr0 ? (proc->mm.rss_anon_pages * PAGE_SIZE) : calc_heap(proc->heap_phys); uint64_t heap_limit = proc->mm.ttbr0 ? (uint64_t)(proc->mm.mmap_top - proc->mm.mmap_bottom) : ((heap + 0xFFF) & ~0xFFF); draw_memory("Heap", xo + stack_width + 50, stack_y, stack_width, stack_height, heap, heap_limit ? heap_limit : PAGE_SIZE); - string flags = string_format("Flags: %x", proc->spsr); + string flags = string_format("Flags: %x", proc->main_thread.spsr); fb_draw_string(&ctx, flags.data, xo, flags_y, scale, system_theme.bg_color); string_free(name); string_free(state); diff --git a/kernel/utils/termhistory/termhistory.c b/kernel/utils/termhistory/termhistory.c index 37d2c1aa..e69de29b 100644 --- a/kernel/utils/termhistory/termhistory.c +++ b/kernel/utils/termhistory/termhistory.c @@ -1,14 +0,0 @@ -#include "files/system_module.h" -#include "files/stack_fs.h" - -system_module termhistory_mod = { - .name = "terminal history", - .mount = "termhistory", - .version = VERSION_NUM(0, 1, 0, 0), - .init = stackfs_init, - .open = stackfs_open, - .read = stackfs_read, - .write = stackfs_write, - .readdir = stackfs_readdir, - .getstat = stackfs_stat -}; \ No newline at end of file diff --git a/kernel/utils/utils.h b/kernel/utils/utils.h index 0b867fb2..d76fea3c 100644 --- a/kernel/utils/utils.h +++ b/kernel/utils/utils.h @@ -13,6 +13,5 @@ static inline bool load_util_mods(){ load_module(&clipboard_mod) && load_module(&language_mod) && load_module(&rng_module) && - load_module(&termhistory_mod) && true; } \ No newline at end of file diff --git a/libs/LibMakefile b/libs/LibMakefile index ca515c3d..4e6a584c 100644 --- a/libs/LibMakefile +++ b/libs/LibMakefile @@ -1,8 +1,3 @@ -#Find the simplemake - #Iterate through each line - #gcc -I../../shared -c file.c -o file.o ../../shared/libshared.a - #Iterate through each line with .o and run - #ar rcs (folder).a *.o BASE_FLAGS := -I. -I../../shared @@ -26,11 +21,8 @@ all: prepare $(TARGET) prepare: mkdir -p $(BUILD_DIR) - @echo "C Sources $(C_SRC)" $(TARGET): $(OBJ) - @echo "Finishing build $(ARCH)" - @echo $(addprefix $(BUILD_DIR)/,$(notdir $(OBJ))) $(VAR) rcs $@ $(OBJ) $(BUILD_DIR)/%.o: %.c diff --git a/libs/regex b/libs/regex index d12ce58c..85bc5e9f 160000 --- a/libs/regex +++ b/libs/regex @@ -1 +1 @@ -Subproject commit d12ce58c54af70f84ac30637077e4dea3b6febae +Subproject commit 85bc5e9ffbc390e7b41aadc98951a017cfe26861 diff --git a/modules/MakefileModule b/modules/MakefileModule index 97e8ef2a..434ec1fd 100644 --- a/modules/MakefileModule +++ b/modules/MakefileModule @@ -13,11 +13,11 @@ endif CFLAGS := $(CFLAGS_BASE) $(BASE_FLAGS) CXXFLAGS := $(CXXFLAGS_BASE) $(BASE_FLAGS) -CLEAN_OBJS := $(shell find $(DRIVER_TARGET) -name "*.o") $(shell find ./common -name "*.o") -CLEAN_DEPS := $(shell find $(DRIVER_TARGET) -name "*.d") $(shell find ./common -name "*.d") -C_SRC := $(shell find $(DRIVER_TARGET) -name "*.c") $(shell find ./common -name "*.c") -CPP_SRC := $(shell find $(DRIVER_TARGET) -name "*.cpp") $(shell find ./common -name "*.cpp") -ASM_SRC := $(shell find $(DRIVER_TARGET) -name "*.S") $(shell find ./common -name "*.S") +CLEAN_OBJS := $(shell find $(DRIVER_TARGET) -name "*.o") $(shell find ./common -name "*.o" 2>/dev/null) +CLEAN_DEPS := $(shell find $(DRIVER_TARGET) -name "*.d") $(shell find ./common -name "*.d" 2>/dev/null) +C_SRC := $(shell find $(DRIVER_TARGET) -name "*.c") $(shell find ./common -name "*.c" 2>/dev/null) +CPP_SRC := $(shell find $(DRIVER_TARGET) -name "*.cpp") $(shell find ./common -name "*.cpp" 2>/dev/null) +ASM_SRC := $(shell find $(DRIVER_TARGET) -name "*.S") $(shell find ./common -name "*.S" 2>/dev/null) OBJ := $(C_SRC:%.c=$(BUILD_DIR)/%.o) $(ASM_SRC:%.S=$(BUILD_DIR)/%.o) $(CPP_SRC:%.cpp=$(BUILD_DIR)/%.o) DEP := $(C_SRC:%.c=$(BUILD_DIR)/%.d) $(ASM_SRC:%.S=$(BUILD_DIR)/%.d) $(CPP_SRC:%.cpp=$(BUILD_DIR)/%.d) diff --git a/modules/audio/virt/audio.cpp b/modules/audio/virt/audio.cpp index 8a31b79e..f6d38000 100644 --- a/modules/audio/virt/audio.cpp +++ b/modules/audio/virt/audio.cpp @@ -304,6 +304,7 @@ system_module audio_module = (system_module){ .name = "audio", .mount = "audio", .version = VERSION_NUM(0, 1, 0, 1), + .owner = 0, .init = init_audio, .fini = 0, .open = audio_open, diff --git a/modules/disk/raspi/disk.cpp b/modules/disk/raspi/disk.cpp index 26c3cd6e..2d221c4b 100644 --- a/modules/disk/raspi/disk.cpp +++ b/modules/disk/raspi/disk.cpp @@ -9,7 +9,7 @@ extern "C" void disk_verbose(){ sdhci_driver.enable_verbose(); } -extern "C" bool init_disk_device(){ +extern "C" bool init_disk_device(system_module *mod){ kprint("Initializing disk"); return sdhci_driver.init(); } @@ -26,6 +26,7 @@ system_module disk_module = (system_module){ .name = "sdhci", .mount = "disk", .version = VERSION_NUM(0, 1, 0, 0), + .owner = 0, .init = init_disk_device, .fini = 0, .open = 0, @@ -35,4 +36,5 @@ system_module disk_module = (system_module){ .truncate = 0, .getstat = 0, .readdir = 0, + .alias_info = {} }; \ No newline at end of file diff --git a/modules/disk/virt/disk.c b/modules/disk/virt/disk.c index 1fd133b4..eb7b9fe4 100644 --- a/modules/disk/virt/disk.c +++ b/modules/disk/virt/disk.c @@ -39,7 +39,7 @@ void disk_verbose(){ }\ }) -bool init_disk_device(){ +bool init_disk_device(system_module *mod){ kprint("Initializing disk"); uint64_t addr = find_pci_device(VIRTIO_VENDOR, VIRTIO_BLK_ID); if (!addr){ diff --git a/modules/graph/raspi/graphics.cpp b/modules/graph/raspi/graphics.cpp index f5f5c7a7..5f356d92 100644 --- a/modules/graph/raspi/graphics.cpp +++ b/modules/graph/raspi/graphics.cpp @@ -12,7 +12,7 @@ static bool _gpu_ready; GPUDriver *gpu_driver; -bool gpu_init(){ +bool gpu_init(system_module *mod){ kprint("[GRAPH] Initializing Raspberry Pi GPU"); gpu_size preferred_screen_size = system_config.preferred_screen_size; gpu_driver = VideoCoreGPUDriver::try_init(preferred_screen_size); @@ -111,6 +111,7 @@ system_module graphics_module = { .name = "graphics", .mount = "graph", .version = VERSION_NUM(0, 1, 0, 0), + .owner = 0, .init = gpu_init, .fini = 0, .open = 0, @@ -119,5 +120,6 @@ system_module graphics_module = { .close = 0, .truncate = 0, .getstat = 0,//TODO: stat - .readdir = 0 + .readdir = 0, + .alias_info = {} }; \ No newline at end of file diff --git a/modules/graph/virt/graphics.cpp b/modules/graph/virt/graphics.cpp index 11ea2e94..0c0dad13 100644 --- a/modules/graph/virt/graphics.cpp +++ b/modules/graph/virt/graphics.cpp @@ -121,6 +121,7 @@ system_module graphics_module = { .name = "graphics", .mount = "graph", .version = VERSION_NUM(0, 1, 0, 0), + .owner = 0, .init = gpu_init, .fini = 0, .open = 0, diff --git a/modules/usb/common/usb_common.cpp b/modules/usb/common/usb_common.cpp index e64bcd02..9527131e 100644 --- a/modules/usb/common/usb_common.cpp +++ b/modules/usb/common/usb_common.cpp @@ -76,6 +76,7 @@ system_module usb_module = (system_module){ .name = "input", .mount = "in", .version = VERSION_NUM(0, 1, 0, 1), + .owner = 0, .init = input_init, .fini = 0, .open = 0, diff --git a/shared b/shared index c8ff6193..1442cef4 160000 --- a/shared +++ b/shared @@ -1 +1 @@ -Subproject commit c8ff6193b2bdce49d5e09a8eb8913cbd14cc31b3 +Subproject commit 1442cef44fcf72143332558c5f86be9f7d9f6ca6 diff --git a/user/UserMakefile b/user/UserMakefile index ad5c48b5..da135fa9 100644 --- a/user/UserMakefile +++ b/user/UserMakefile @@ -2,11 +2,13 @@ include ../../common.mk CPPFLAGS := -I. -I../../shared CFLAGS := $(CFLAGS_BASE) $(CPPFLAGS) +CXXFLAGS := $(CXXFLAGS_BASE) $(CPPFLAGS) LDFLAGS := -emain CLEAN_OBJS := $(shell find . -name '*.o') CLEAN_DEPS := $(shell find . -name '*.d') C_SRC := $(shell find . -name '*.c') +CPP_SRC := $(shell find . -name '*.cpp') OBJ := $(C_SRC:%.c=$(BUILD_DIR)/%.o) $(CPP_SRC:%.cpp=$(BUILD_DIR)/%.o) DEP := $(C_SRC:%.c=$(BUILD_DIR)/%.d) $(CPP_SRC:%.cpp=$(BUILD_DIR)/%.d) @@ -39,6 +41,10 @@ $(BUILD_DIR)/%.o: %.c @mkdir -p $(dir $@) $(VCC) $(CFLAGS) -c -MMD -MP $< -o $@ +$(BUILD_DIR)/%.o: %.cpp + @mkdir -p $(dir $@) + $(VCXX) $(CXXFLAGS) -c -MMD -MP $< -o $@ + clean: $(RM) $(CLEAN_OBJS) $(CLEAN_DEPS) $(TARGET) $(RM) -r $(PACKAGE) $(BUILD_DIR) @@ -46,4 +52,4 @@ clean: dump: all $(ARCH)objdump -S $(NAME).red/$(NAME).elf > dump --include $(DEP) +-include $(DEP) \ No newline at end of file diff --git a/user/demo/default_process.c b/user/demo/default_process.c index 21713a24..ca841dc2 100644 --- a/user/demo/default_process.c +++ b/user/demo/default_process.c @@ -12,6 +12,7 @@ #include "utils/clipboard.h" #include "math/math.h" #include "draw/textdraw.h" +#include "environment/env_types.h" draw_ctx ctx = {}; @@ -186,8 +187,9 @@ int copypaste(){ bool should_quit = false; bool on_quit(signal_info_t *do_not_use_this){ - print("I'm told to quit"); + msleep(3000); should_quit = true; + // while (true) printl("I'm told to quit"); return true; } @@ -202,6 +204,15 @@ struct { char* name; int (*fn)(); } demos[] = { }; int main(int argc, char* argv[]){ + + handle_signal(SIG_QUIT, on_quit); + // send_signal(SIG_QUIT, 7);//TODO: get own procid? + + window_info_t info = { + .name = "Demo program", + .name_length = 12 + }; + env_set_window_info(&info); request_draw_ctx(&ctx); @@ -225,20 +236,27 @@ int main(int argc, char* argv[]){ string f = string_format("[%i]: %s\n",i+1, demos[i].name); range.size = f.length; fb_continuous_draw_text(&ctx, draw_text_render, &cursor, slice_from_string(f), &range, rect, &size, (gpu_point){}, text_fmt, (text_format_arr){ }); - print("%i,%i - %i,%i",range.start,range.size,cursor.x,cursor.y); string_free(f); } while (true) { commit_draw_ctx(&ctx); + if (should_quit) { + print("SIG QUIT"); + halt(0); + } kbd_event ev = {}; if (read_event(&ev)){ if (ev.type == KEY_PRESS){ if (ev.key >= KEY_1 && ev.key <= (KEY_1 + count - 1)){ int index = ev.key - KEY_1; - if (index >= 0 && index < count) + if (index >= 0 && index < count){ + fb_clear(&ctx, 0); + commit_draw_ctx(&ctx); return demos[index].fn(); + } } + if (ev.key == KEY_ESC) halt(0); } } } diff --git a/user/filebrowser/main.c b/user/filebrowser/main.c index 51bb16b5..51b1b96f 100644 --- a/user/filebrowser/main.c +++ b/user/filebrowser/main.c @@ -3,8 +3,46 @@ #include "input_keycodes.h" #include "data/struct/stack.h" #include "header_utils/filebrowser.h" +#include "files/vfs.h" + +size_t test_fn(file *fd, const char *c, size_t s, file_offset off){ + print("Test button pressed"); + return 0; +} + +void menu_init(){ + make_entry("File", backing_virtual, entry_directory, 0, (buffer){}); + make_entry("File" "/" "Hello", backing_virtual, entry_file, 0, (buffer){}); + make_entry("Edit", backing_virtual, entry_directory, 0, (buffer){}); + make_entry("Edit/World", backing_virtual, entry_directory, 0, (buffer){}); + make_complex_entry("File/Test", backing_transform, entry_file, 0, (file_actions){.write = test_fn}, (string){}); +} + +size_t custom_readdir(const char *path, void *buf, size_t size, file_offset *offset){ + print(">>>>>>>Hello"); + size_t ret = vfs_readdir(path, buf, size, offset); + print(">>> %x",ret); + return ret; +} + +system_module menu_mod = { + .name = "demo menu", + .mount = "menu", + //TODO: can init be brought back now? + .version = VERSION_NUM(0, 1, 0, 0), + .open = vfs_open, + .read = vfs_read, + .write = vfs_write, + .getstat = vfs_stat, + .readdir = custom_readdir, +}; int main(){ + menu_init(); + load_fsmodule(&menu_mod, false); + + swritef("/environment/menu", 0, 0, false); + request_draw_ctx(&filebrowser_ctx); files = stack_create(sizeof(file_data),32); diff --git a/user/launcher/main.c b/user/launcher/main.c index 6560aeca..5ae2c64b 100644 --- a/user/launcher/main.c +++ b/user/launcher/main.c @@ -181,6 +181,7 @@ void activate_current(){ u16 pid = exec(entry->path.data, 0, 0, EXEC_MODE_DEFAULT); if (!pid) { print("[LAUNCHER error] failed to launch process"); + rendered_full = false; return; } halt(0);//TODO: remove any references to resuming after the process is closed diff --git a/user/terminal/main.c b/user/terminal/main.c deleted file mode 100644 index cc0886c0..00000000 --- a/user/terminal/main.c +++ /dev/null @@ -1,319 +0,0 @@ -#include "syscalls/syscalls.h" -#include "draw/textdraw.h" -#include "shell/shell.h" -#include "shell/sheldon/sheldon.h" -#include "environment/env_types.h" -#include "data/serialize/binary_serial.h" -#include "kbd_helper.h" -#include "memory/memory.h" -#include "utils/embedded_fmt/tcf.h" -#include "files/helpers.h" -#include "header_utils/screenprinter.h" -#include "header_utils/composite.h" - -embedded_fmt input_format = {}; - -#define INPUT_MARGIN 10 -#define INPUT_HEIGHT (line_height+(INPUT_MARGIN*2)) - -int history_ptr = 0; -int history_count = 0; - -bool headless = false; - -bool cursor_on = false; -u64 cursor_blink_time = 500; - -u32 bg_color; - -buffer input_buf = {}; - -draw_ctx ctx = {}; - -gpu_rect screen_rect = {}; - -shell_handle* main_shell; - -void flush(shell_handle *handle, bool can_scroll); - -static char log_buf[1024]; - -int debug_print(const char *fmt, ...){ - __attribute__((aligned(16))) va_list args; - va_start(args, fmt); - memset(log_buf, 0, 1024); - size_t n = string_format_va_buf(fmt, log_buf, sizeof(log_buf), args); - va_end(args); - if (n >= sizeof(log_buf)) log_buf[sizeof(log_buf)-1] = '\0'; - printl(log_buf); - return 0; -} - -shell_handle* make_default_shell(shell_bindings bindings){ - return create_sheldon(bindings, 0); -} - -void clear(shell_handle *handle){ - if (main_shell && main_shell != handle) return; - // buffer_wipe(&contents); - fb_clear(&ctx, screen_printer_formatting.current_bg_color); -} - -bool return_from_parse = false; - -void put_char(shell_handle *handle, char c){ - // print("New char %c %x %x %i",c,handle,main_shell,contents.cursor); - if (!c || (main_shell && main_shell != handle)) return; - bool render = true; - if (embedded_fmt_parse(&screen_printer_formatting, c)){ - render = false; - return_from_parse = true; - if (screen_printer_formatting.wipe){ - screen_printer_formatting.wipe = false; - clear(handle); - return; - } - } - if (!render) - return; - if (headless) - serial_transmit(c); - else { - screen_printer_put_char(c); - if (return_from_parse) flush(handle, true); - return_from_parse = false; - } -} - -void flush(shell_handle *handle, bool can_scroll){ - // print("Flush %v {%i,%i}",slice_from_buffer(&contents),rerender_range.start,rerender_range.size); - if (main_shell && main_shell != handle) return; - - screen_print_flush(can_scroll); -} - -void refresh_input(){ - fb_fill_rect(&ctx, 0, ctx.height-INPUT_HEIGHT, ctx.width, INPUT_HEIGHT, input_format.current_bg_color); - gpu_size offset = fb_draw_slice(&ctx, SLICE("> "), 0, ctx.height-INPUT_HEIGHT+INPUT_MARGIN, TEXT_SCALE, input_format.current_text_color); - fb_draw_slice(&ctx, slice_from_buffer(&input_buf), offset.width, ctx.height-INPUT_HEIGHT+INPUT_MARGIN, TEXT_SCALE, input_format.current_text_color); - if (cursor_on) - fb_fill_rect(&ctx, offset.width + (char_width * input_buf.cursor), ctx.height-INPUT_HEIGHT+INPUT_MARGIN, char_width, INPUT_HEIGHT-(INPUT_MARGIN*2), input_format.current_text_color); - commit_draw_ctx(&ctx); -} - -void bell(shell_handle *handle){ - if (main_shell && main_shell != handle) return; - print("DING"); -} - -void ascii_cmd(shell_handle *handle, char cmd, u16 proc_id){ - if (main_shell && main_shell != handle) return; - switch (cmd){ - case ASCII_CMD_ETX: - send_signal(SIG_QUIT, proc_id); - break; - case ASCII_CMD_SUB: - send_signal(SIG_STOP, proc_id); - break; - case ASCII_CMD_CAN: - send_signal(SIG_CONT, proc_id); - break; - default: break; - } -} - -void console_ctrl(shell_handle *handle, console_ctrls ctrl){ - if (main_shell && main_shell != handle) return; - switch (ctrl) { - case console_ctrl_close: halt(0); - default: break; - } -} - -void emit_data(structdef field, sizedptr data, bool is_allocated){ - // if (main_shell && main_shell != handle) return; - print("[TERMINAL implementation error] structured data displaying not implemented"); - // if (!data.ptr || !data.size) return; - // switch (field.type) { - // case binary_type_i8: print("%S: %i",field.name,*(i8*)data.ptr); break; - // case binary_type_i16: print("%S: %i",field.name,*(i16*)data.ptr); break; - // case binary_type_i32: print("%S: %i",field.name,*(i32*)data.ptr); break; - // case binary_type_i64: print("%S: %i",field.name,*(i64*)data.ptr); break; - // case binary_type_float: print("%S: %f",field.name,*(float*)data.ptr); break; - // case binary_type_double: print("%S: %f",field.name,*(double*)data.ptr); break; - // case binary_type_string: print("%S: %v",field.name,data); break; - // default: return; - // } - // if (is_allocated) release((void*)data.ptr); -} - -void flush_proxy(shell_handle *handle){ - flush(handle, true); -} - -shell_bindings terminal_bindings = (shell_bindings){ - .console_output = put_char, - .console_flush = flush_proxy, - .console_clean = clear, - .console_bell = bell, - .console_ascii_cmd = ascii_cmd, - .console_control = console_ctrl -}; - -shell_handle* create_shell(){ - shell_handle *handle = make_default_shell(terminal_bindings); - if (!handle) return 0; - return handle; -} - -bool erase(bool forward){ - if (forward && input_buf.cursor >= input_buf.buffer_size) return false; - if (!buffer_delete(&input_buf, input_buf.cursor + forward, 1)) return false; - - refresh_input(); - return true; -} - -bool run_command(){ - - bool success = false; - - screen_printer_append("\r\n"); - - write_full_file("/termhistory", input_buf.buffer, input_buf.buffer_size); - history_count++; - history_ptr = history_count; - - if (run_cmd(main_shell, slice_from_buffer(&input_buf))) success = true; - - buffer_wipe(&input_buf); - return success; -} - -bool move_buf_cursor(i64 amount){ - if (!amount) return false; - uptr old_in_c = input_buf.cursor; - if (buffer_seek(&input_buf, amount, false) == old_in_c) return false; - refresh_input(); - return true; -} - -bool scroll_history(i64 amount){ - int new_history_ptr = history_ptr + amount; - if (new_history_ptr < 0) new_history_ptr = 0; - string file = string_format("/termhistory/%i",new_history_ptr); - fs_stat st = {}; - if (statf(file.data, &st)){ - size_t hist_size = 0; - char *history = read_full_file(file.data, &hist_size); - if (input_buf.buffer) buffer_destroy(&input_buf); - input_buf = (buffer){ - .buffer = history, - .buffer_size = hist_size, - .limit = hist_size, - .options = buffer_can_grow, - .cursor = hist_size - }; - history_ptr = new_history_ptr; - return true; - } - buffer_wipe(&input_buf); - return false; -} - -void handle_mouse(){ - mouse_data data = {}; - get_mouse_status(&data); - if (data.raw.scroll){ - screen_print_scroll(data.raw.scroll, false); - } -} - -bool handle_input(){ - - handle_mouse(); - - kbd_event event; - if (!read_event(&event)) return false; - if (event.type == KEY_RELEASE) return true; - if (handle_modifier(&event)) return true; - - char key = event.key; - char readable = hid_to_char((uint8_t)key, current_modifier, special_key); - - if (key == KEY_ENTER || key == KEY_KPENTER) return run_command(); - - if (key == KEY_BACKSPACE) return erase(false); - if (key == KEY_DELETE) return erase(true); - - if (key == KEY_UP) return scroll_history(-1); - if (key == KEY_DOWN) return scroll_history(1); - - if (key == KEY_LEFT) return move_buf_cursor(-1); - if (key == KEY_RIGHT) return move_buf_cursor(1); - - if (key == KEY_PAGEDOWN || key == KEY_PAGEUP) - screen_print_scroll(key == KEY_PAGEDOWN ? -1 : 1, false); - - if (!readable) return false; - - if (!input_buf.buffer) input_buf = buffer_create(0x100, buffer_can_grow); - - buffer_write_lim(&input_buf, &readable, 1); - refresh_input(); - - flush(main_shell, true); - - return true; - -} - -void toggle_cursor(){ - cursor_on = !cursor_on; - refresh_input(); -} - -int main(){ - request_app_ctx(&ctx); - - screen_printer_init(dummy_draw_ctx(ctx.width, ctx.height-INPUT_HEIGHT)); - - u32 color_buf[2] = {}; - sreadf("/theme", &color_buf, sizeof(uint64_t)); - if ((color_buf[0] & 0xFF000000) == 0) color_buf[0] |= 0xFF000000; - if ((color_buf[1] & 0xFF000000) == 0) color_buf[1] |= 0xFF000000; - screen_printer_formatting.default_bg_color = screen_printer_formatting.current_bg_color = color_buf[0]; - screen_printer_formatting.default_text_color = screen_printer_formatting.current_text_color = color_buf[1]; - - init_tcf(&screen_printer_formatting); - - memcpy(&input_format, &screen_printer_formatting, sizeof(text_format)); - - fb_clear(&ctx, screen_printer_formatting.current_bg_color); - - main_shell = create_shell(); - - current_shell = main_shell; - - u64 cursor_current = 0; - - u64 last_time = get_time(); - refresh_input(); - while (true){ - // append("Bonjour %.3i \t",i++); - u64 current_time = get_time(); - cursor_current += (current_time-last_time); - if (cursor_current >= cursor_blink_time){ - toggle_cursor(); - cursor_current = 0; - } - last_time = current_time; - handle_input(); - msleep(1); - ctx.full_redraw = true; - composite(&printer_ctx, (int_point){}, 1, &ctx); - commit_draw_ctx(&ctx); - } - - return 0; -} \ No newline at end of file diff --git a/user/terminal/terminal.cpp b/user/terminal/terminal.cpp index faa9d509..af67631c 100644 --- a/user/terminal/terminal.cpp +++ b/user/terminal/terminal.cpp @@ -49,7 +49,15 @@ extern void term_ascii_cmd(shell_handle *handle, char cmd, u16 proc_id); extern void term_console_ctrl(shell_handle *handle, console_ctrls ctrl); shell_handle* Terminal::create_shell(){ - return create_sheldon(0); + shell_bindings terminal_bindings = (shell_bindings){ + .console_output = term_put_char, + .console_flush = term_flush, + .console_clean = term_clear, + .console_bell = term_bell, + .console_ascii_cmd = term_ascii_cmd, + .console_control = term_console_ctrl + }; + return create_sheldon(terminal_bindings, 0, 0); } void Terminal::ctrl(console_ctrls ctrl){ @@ -389,4 +397,4 @@ void Terminal::refresh(){ bool Terminal::screen_ready(){ return !headless; -} +} \ No newline at end of file