From f0d7ed7743191ca28fc62454c8b1df142326779a Mon Sep 17 00:00:00 2001 From: "K. Lange" Date: Mon, 31 Jan 2022 21:08:11 +0900 Subject: [PATCH] aarch64: fixup clone(), add mmu_free(), cache stuff for ld.so --- kernel/arch/aarch64/mmu.c | 47 +++++++++++++++++++++++++++++++++++++- kernel/arch/aarch64/user.c | 15 ++++++++++++ kernel/misc/elf64.c | 5 ++++ kernel/sys/process.c | 6 ++--- kernel/sys/syscall.c | 9 ++++++++ linker/linker.c | 8 ++++++- 6 files changed, 85 insertions(+), 5 deletions(-) diff --git a/kernel/arch/aarch64/mmu.c b/kernel/arch/aarch64/mmu.c index 7cc2d437..4cd7902e 100644 --- a/kernel/arch/aarch64/mmu.c +++ b/kernel/arch/aarch64/mmu.c @@ -516,10 +516,54 @@ size_t mmu_used_memory(void) { void mmu_free(union PML * from) { /* walk and free pages */ + if (!from) { + printf("can't clear NULL directory\n"); + return; + } + + spin_lock(frame_alloc_lock); + for (size_t i = 0; i < 256; ++i) { + if (from[i].bits.present) { + union PML * pdp_in = mmu_map_from_physical((uintptr_t)from[i].bits.page << PAGE_SHIFT); + for (size_t j = 0; j < 512; ++j) { + if (pdp_in[j].bits.present) { + union PML * pd_in = mmu_map_from_physical((uintptr_t)pdp_in[j].bits.page << PAGE_SHIFT); + for (size_t k = 0; k < 512; ++k) { + if (pd_in[k].bits.present) { + union PML * pt_in = mmu_map_from_physical((uintptr_t)pd_in[k].bits.page << PAGE_SHIFT); + for (size_t l = 0; l < 512; ++l) { + uintptr_t address = ((i << (9 * 3 + 12)) | (j << (9*2 + 12)) | (k << (9 + 12)) | (l << PAGE_SHIFT)); + /* Do not free shared mappings; SHM subsystem does that for SHM, devices don't need it. */ + if (address >= USER_DEVICE_MAP && address <= USER_SHM_HIGH) continue; + if (pt_in[l].bits.present) { + /* Free only user pages */ + if (pt_in[l].bits.ap & 1) { + mmu_frame_clear((uintptr_t)pt_in[l].bits.page << PAGE_SHIFT); + pt_in[l].raw = 0; + //free_page_maybe(pt_in,l,address); + } + } + } + mmu_frame_clear((uintptr_t)pd_in[k].bits.page << PAGE_SHIFT); + pd_in[k].raw = 0; + } + } + mmu_frame_clear((uintptr_t)pdp_in[j].bits.page << PAGE_SHIFT); + pdp_in[j].raw = 0; + } + } + mmu_frame_clear((uintptr_t)from[i].bits.page << PAGE_SHIFT); + from[i].raw = 0; + } + } + + mmu_frame_clear((((uintptr_t)from) & PHYS_MASK)); + asm volatile ("dsb ishst\ntlbi vmalle1is\ndsb ish\nisb" ::: "memory"); + spin_unlock(frame_alloc_lock); } union PML * mmu_get_kernel_directory(void) { - return (union PML*)&init_page_region; + return mmu_map_from_physical((uintptr_t)&init_page_region); } void mmu_set_directory(union PML * new_pml) { @@ -586,6 +630,7 @@ void mmu_unmap_module(uintptr_t start_address, size_t size) { } int mmu_copy_on_write(uintptr_t address) { + return 1; } diff --git a/kernel/arch/aarch64/user.c b/kernel/arch/aarch64/user.c index f50f0269..73696d5f 100644 --- a/kernel/arch/aarch64/user.c +++ b/kernel/arch/aarch64/user.c @@ -742,6 +742,11 @@ void aarch64_sync_enter(struct regs * r) { asm volatile ("mrs %0, ELR_EL1" : "=r"(elr)); asm volatile ("mrs %0, SPSR_EL1" : "=r"(spsr)); + if (elr == 0xFFFFB00F && far == 0xFFFFB00F) { + task_exit(0); + __builtin_unreachable(); + } + if ((esr >> 26) == 0x15) { #if 0 printf("%s: syscall(%ld) puts sp at %#zx with base of %#zx\n", this_core->current_process->name, r->x0, (uintptr_t)r, @@ -857,6 +862,16 @@ void arch_pause(void) { switch_next(); } +void arch_clear_icache(uintptr_t start, uintptr_t end) { + for (uintptr_t x = start; x < end; x += 64) { + if (!mmu_validate_user_pointer((void*)x, 64, MMU_PTR_WRITE)) continue; + asm volatile ("dc cvau, %0" :: "r"(x)); + } + for (uintptr_t x = start; x < end; x += 64) { + if (!mmu_validate_user_pointer((void*)x, 64, MMU_PTR_WRITE)) continue; + asm volatile ("ic ivau, %0" :: "r"(x)); + } +} /** diff --git a/kernel/misc/elf64.c b/kernel/misc/elf64.c index 9bcb2b97..fa7c1d88 100644 --- a/kernel/misc/elf64.c +++ b/kernel/misc/elf64.c @@ -282,6 +282,11 @@ int elf_exec(const char * path, fs_node_t * file, int argc, const char *const ar *(char*)(phdr.p_vaddr + i) = 0; } + #ifdef __aarch64__ + extern void arch_clear_icache(uintptr_t,uintptr_t); + arch_clear_icache(phdr.p_vaddr, phdr.p_vaddr + phdr.p_memsz); + #endif + if (phdr.p_vaddr + phdr.p_memsz > heapBase) { heapBase = phdr.p_vaddr + phdr.p_memsz; } diff --git a/kernel/sys/process.c b/kernel/sys/process.c index dc775872..c75c1559 100644 --- a/kernel/sys/process.c +++ b/kernel/sys/process.c @@ -1378,10 +1378,11 @@ pid_t clone(uintptr_t new_stack, uintptr_t thread_func, uintptr_t arg) { /* different calling convention */ #if defined(__x86_64__) r.rdi = arg; + PUSH(new_stack, uintptr_t, (uintptr_t)0xFFFFB00F); #elif defined(__aarch64__) r.x0 = arg; + r.x30 = 0xFFFFB00F; #endif - PUSH(new_stack, uintptr_t, (uintptr_t)0xFFFFB00F); PUSH(sp, struct regs, r); new_proc->syscall_registers = (void*)sp; #if defined(__x86_64__) @@ -1391,8 +1392,7 @@ pid_t clone(uintptr_t new_stack, uintptr_t thread_func, uintptr_t arg) { #elif defined(__aarch64__) new_proc->syscall_registers->user_sp = new_stack; new_proc->syscall_registers->x29 = new_stack; - //new_proc->syscall_registers->x30 = thread_func; - new_proc->thread.context.saved[14] = thread_func; + new_proc->thread.context.saved[10] = thread_func; #endif new_proc->thread.context.sp = sp; new_proc->thread.context.bp = bp; diff --git a/kernel/sys/syscall.c b/kernel/sys/syscall.c index 452e0031..ba2c9d31 100644 --- a/kernel/sys/syscall.c +++ b/kernel/sys/syscall.c @@ -95,6 +95,15 @@ long sys_sysfunc(long fn, char ** args) { printf("kdebug: not implemented\n"); return -EINVAL; + case 42: + #ifdef __aarch64__ + PTR_VALIDATE(&args[0]); + PTR_VALIDATE(&args[1]); + extern void arch_clear_icache(uintptr_t,uintptr_t); + arch_clear_icache((uintptr_t)args[0], (uintptr_t)args[1]); + #endif + return 0; + case TOARU_SYS_FUNC_INSMOD: /* Linux has init_module as a system call? */ if (this_core->current_process->user != 0) return -EACCES; diff --git a/linker/linker.c b/linker/linker.c index fcb18e9c..11719c09 100644 --- a/linker/linker.c +++ b/linker/linker.c @@ -115,6 +115,11 @@ typedef struct elf_object { static elf_t * _main_obj = NULL; +static void clear_cache(uintptr_t start, uintptr_t end) { + char * data[] = {(char*)start,(char*)end}; + sysfunc(42, data); +} + /* Locate library for LD_LIBRARY PATH */ static char * find_lib(const char * file) { @@ -298,6 +303,7 @@ static uintptr_t object_load(elf_t * object, uintptr_t base) { /* Copy the code into memory */ fseek(object->file, phdr.p_offset, SEEK_SET); fread((void *)(base + phdr.p_vaddr), phdr.p_filesz, 1, object->file); + clear_cache(base + phdr.p_vaddr, base + phdr.p_vaddr + phdr.p_filesz); /* Zero the remaining area */ size_t r = phdr.p_filesz; @@ -431,7 +437,7 @@ static int object_relocate(elf_t * object) { hashmap_set(dumb_symbol_table, symname, (void*)(table->st_value + object->base)); table->st_value = table->st_value + object->base; } else { - table->st_value = hashmap_get(dumb_symbol_table, symname); + table->st_value = (uintptr_t)hashmap_get(dumb_symbol_table, symname); } } else { table->st_value = table->st_value + object->base;