aarch64: fixup clone(), add mmu_free(), cache stuff for ld.so

This commit is contained in:
K. Lange 2022-01-31 21:08:11 +09:00
parent f0409ff120
commit f0d7ed7743
6 changed files with 85 additions and 5 deletions

View File

@ -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;
}

View File

@ -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));
}
}
/**

View File

@ -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;
}

View File

@ -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;

View File

@ -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;

View File

@ -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;