diff --git a/arch/arm64/kernel/module.c b/arch/arm64/kernel/module.c index f01d8b3328cb..051fd7a3ba63 100644 --- a/arch/arm64/kernel/module.c +++ b/arch/arm64/kernel/module.c @@ -524,39 +524,36 @@ static int module_init_hyp(const Elf_Ehdr *hdr, const Elf_Shdr *sechdrs, .end = (void *)s->sh_addr + s->sh_size, }; - s = find_section(hdr, sechdrs, ".hyp.bss"); - if (!s) - return -ENOEXEC; - - mod->arch.hyp.bss = (struct pkvm_module_section) { - .start = (void *)s->sh_addr, - .end = (void *)s->sh_addr + s->sh_size, - }; - - s = find_section(hdr, sechdrs, ".hyp.rodata"); - if (!s) - return -ENOEXEC; - - mod->arch.hyp.rodata = (struct pkvm_module_section) { - .start = (void *)s->sh_addr, - .end = (void *)s->sh_addr + s->sh_size, - }; - - s = find_section(hdr, sechdrs, ".hyp.data"); - if (!s) - return -ENOEXEC; - - mod->arch.hyp.data = (struct pkvm_module_section) { - .start = (void *)s->sh_addr, - .end = (void *)s->sh_addr + s->sh_size, - }; - s = find_section(hdr, sechdrs, ".hyp.reloc"); if (!s) return -ENOEXEC; mod->arch.hyp.relocs = (void *)s->sh_addr; mod->arch.hyp.nr_relocs = s->sh_size / sizeof(*mod->arch.hyp.relocs); + + s = find_section(hdr, sechdrs, ".hyp.bss"); + if (s && s->sh_size) { + mod->arch.hyp.bss = (struct pkvm_module_section) { + .start = (void *)s->sh_addr, + .end = (void *)s->sh_addr + s->sh_size, + }; + } + + s = find_section(hdr, sechdrs, ".hyp.rodata"); + if (s && s->sh_size) { + mod->arch.hyp.rodata = (struct pkvm_module_section) { + .start = (void *)s->sh_addr, + .end = (void *)s->sh_addr + s->sh_size, + }; + } + + s = find_section(hdr, sechdrs, ".hyp.data"); + if (s && s->sh_size) { + mod->arch.hyp.data = (struct pkvm_module_section) { + .start = (void *)s->sh_addr, + .end = (void *)s->sh_addr + s->sh_size, + }; + } #endif return 0; } diff --git a/arch/arm64/kvm/pkvm.c b/arch/arm64/kvm/pkvm.c index 4ff98340fcb2..cb347c4710a0 100644 --- a/arch/arm64/kvm/pkvm.c +++ b/arch/arm64/kvm/pkvm.c @@ -601,8 +601,8 @@ int __pkvm_load_el2_module(struct module *this, unsigned long *token) }; void *start, *end, *hyp_va; kvm_nvhe_reloc_t *endrel; + int ret, i, secs_first; size_t offset, size; - int ret, i; if (!is_protected_kvm_enabled()) return -EOPNOTSUPP; @@ -619,8 +619,13 @@ int __pkvm_load_el2_module(struct module *this, unsigned long *token) return -ENODEV; } + /* Missing or empty module sections are placed first */ sort(secs_map, ARRAY_SIZE(secs_map), sizeof(secs_map[0]), __pkvm_cmp_mod_sec, NULL); - start = secs_map[0].sec->start; + for (secs_first = 0; secs_first < ARRAY_SIZE(secs_map); secs_first++) { + start = secs_map[secs_first].sec->start; + if (start) + break; + } end = secs_map[ARRAY_SIZE(secs_map) - 1].sec->end; size = end - start; @@ -642,7 +647,8 @@ int __pkvm_load_el2_module(struct module *this, unsigned long *token) endrel = (void *)mod->relocs + mod->nr_relocs * sizeof(*endrel); kvm_apply_hyp_module_relocations(start, hyp_va, mod->relocs, endrel); - ret = pkvm_map_module_sections(secs_map, hyp_va, ARRAY_SIZE(secs_map)); + ret = pkvm_map_module_sections(secs_map + secs_first, hyp_va, + ARRAY_SIZE(secs_map) - secs_first); if (ret) { kvm_err("Failed to map EL2 module page: %d\n", ret); module_put(this);