mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-07 03:15:31 +09:00
ANDROID: KVM: arm64: Support missing pKVM module sections
pKVM modules being rather small, it is expected for some basic sections to be missing or empty (especially rodata and data). Make those optional in the loader. Bug: 269245057 Change-Id: I874050230de5cb4b3b29d316663400bb221e2021 Signed-off-by: Vincent Donnefort <vdonnefort@google.com>
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user