diff --git a/kernel/arch/aarch64/mmu.c b/kernel/arch/aarch64/mmu.c index 0e7f2cbd..6c27c784 100644 --- a/kernel/arch/aarch64/mmu.c +++ b/kernel/arch/aarch64/mmu.c @@ -699,9 +699,23 @@ void * mmu_map_mmio_region(uintptr_t physical_address, size_t size) { return out; } +static uintptr_t module_base_address = MODULE_BASE_START; + void * mmu_map_module(size_t size) { - printf("attempt to map module\n"); - return NULL; + if (size & PAGE_LOW_MASK) { + size += (PAGE_LOW_MASK + 1) - (size & PAGE_LOW_MASK); + } + + spin_lock(module_space_lock); + void * out = (void*)module_base_address; + for (size_t i = 0; i < size; i += PAGE_SIZE) { + union PML * p = mmu_get_page(module_base_address + i, MMU_GET_MAKE); + mmu_frame_allocate(p, MMU_FLAG_KERNEL | MMU_FLAG_WRITABLE); + } + module_base_address += size; + spin_unlock(module_space_lock); + + return out; } void mmu_unmap_module(uintptr_t start_address, size_t size) { @@ -837,5 +851,5 @@ void mmu_init(uintptr_t memaddr, size_t memsize, uintptr_t firstFreePage, uintpt heapStart = (char*)KERNEL_HEAP_START + bytesOfFrames; lowest_available = (firstFreePage + bytesOfFrames) - memaddr; - + module_base_address = endOfRamDisk + MODULE_BASE_START; } diff --git a/kernel/misc/elf64.c b/kernel/misc/elf64.c index fa7c1d88..33ab19a1 100644 --- a/kernel/misc/elf64.c +++ b/kernel/misc/elf64.c @@ -99,6 +99,11 @@ int elf_module(char ** args) { memset((void*)sectionHeader->sh_addr, 0, sectionHeader->sh_size); } else { sectionHeader->sh_addr = (uintptr_t)(module_load_address + sectionHeader->sh_offset); + if (sectionHeader->sh_addralign && + (sectionHeader->sh_addr & (sectionHeader->sh_addralign -1))) { + dprintf("mod: probably not aligned correctly: %#zx %ld\n", + sectionHeader->sh_addr, sectionHeader->sh_addralign); + } } } @@ -125,8 +130,12 @@ int elf_module(char ** args) { if (symTable[sym].st_shndx > 0 && symTable[sym].st_shndx < SHN_LOPROC) { Elf64_Shdr * sh_hdr = (Elf64_Shdr*)(module_load_address + header.e_shoff + header.e_shentsize * symTable[sym].st_shndx); symTable[sym].st_value = symTable[sym].st_value + sh_hdr->sh_addr; + dprintf("mod: bind local symbol '%s' to %#zx\n", + symTable[sym].st_name ? (symNames + symTable[sym].st_name) : "(unnamed)", symTable[sym].st_value); } else if (symTable[sym].st_shndx == SHN_UNDEF) { symTable[sym].st_value = (uintptr_t)ksym_lookup(symNames + symTable[sym].st_name); + dprintf("mod: bind kernel symbol '%s' to %#zx\n", + symTable[sym].st_name ? (symNames + symTable[sym].st_name) : "(unnamed)", symTable[sym].st_value); } if (symTable[sym].st_name && !strcmp(symNames + symTable[sym].st_name, "metadata")) { @@ -156,6 +165,7 @@ int elf_module(char ** args) { for (unsigned int rela = 0; rela < sectionHeader->sh_size / sizeof(Elf64_Rela); ++rela) { uintptr_t target = table[rela].r_offset + targetSection->sh_addr; switch (ELF64_R_TYPE(table[rela].r_info)) { +#if defined(__x86_64__) case R_X86_64_64: *(uint64_t*)target = symbolTable[ELF64_R_SYM(table[rela].r_info)].st_value + table[rela].r_addend; break; @@ -165,13 +175,16 @@ int elf_module(char ** args) { case R_X86_64_PC32: *(uint32_t*)target = symbolTable[ELF64_R_SYM(table[rela].r_info)].st_value + table[rela].r_addend - target; break; +#endif default: + dprintf("mod: unsupported relocation %ld found\n", ELF64_R_TYPE(table[rela].r_info)); error = EINVAL; - goto _unmap_module; } } } + if (error) goto _unmap_module; + if (hashmap_has(_modules_table, moduleData->name)) { error = EEXIST; goto _unmap_module; diff --git a/kernel/sys/syscall.c b/kernel/sys/syscall.c index 1a464239..dbfd07a4 100644 --- a/kernel/sys/syscall.c +++ b/kernel/sys/syscall.c @@ -107,10 +107,6 @@ long sys_sysfunc(long fn, char ** args) { case TOARU_SYS_FUNC_INSMOD: /* Linux has init_module as a system call? */ if (this_core->current_process->user != 0) return -EACCES; - #if defined(__aarch64__) - /* TODO: Most modules are not right for this and we are missing relocations */ - return -EINVAL; - #endif PTR_VALIDATE(args); if (!args) return -EFAULT; PTR_VALIDATE(args[0]);