On Tuesday 31 October 2017 07:49 PM, Naveen N . Rao wrote:
Hi Kamalesh,
Sorry for the late review. Overall, the patch looks good to me. So:
Acked-by: Naveen N. Rao <naveen.n.rao@xxxxxxxxxxxxxxxxxx>
However, I have a few minor comments which can be addressed in a
subsequent patch.
Thanks for the review.
[...]
diff --git a/arch/powerpc/kernel/module_64.c b/arch/powerpc/kernel/module_64.c
index 0b0f896..005aaea 100644
--- a/arch/powerpc/kernel/module_64.c
+++ b/arch/powerpc/kernel/module_64.c
[...]
@@ -239,10 +257,19 @@ static void relaswap(void *_x, void *_y, int size)
/* Get size of potential trampolines required. */
static unsigned long get_stubs_size(const Elf64_Ehdr *hdr,
- const Elf64_Shdr *sechdrs)
+ const Elf64_Shdr *sechdrs,
+ struct module *me)
{
/* One extra reloc so it's always 0-funcaddr terminated */
unsigned long relocs = 1;
You might want to get rid of 'relocs' above and simply use the below
two.
+ /*
+ * size of livepatch stub is 28 instructions, whereas the
+ * non-livepatch stub requires 7 instructions. Account for
+ * different stub sizes and track the livepatch relocation
+ * count in me->arch.klp_relocs.
+ */
+ unsigned long sec_relocs = 0;
+ unsigned long klp_relocs = 0;
You should also initialize this to 1 (similar to relocs above) for use
in the iterators below. Or, update the iterators to use
me->arch.klp_relocs (1)
relocs is Sum(sec_relocs), whereas per section relocation count is
assigned to sec_relocs. If the section is livepatch section, then it
added to klp_relocs or else to relocs. sec_relocs acts like a temp
variable to hold the current section relocation count.
unsigned i;
/* Every relocated section... */
@@ -262,9 +289,14 @@ static unsigned long get_stubs_size(const Elf64_Ehdr *hdr,
sechdrs[i].sh_size / sizeof(Elf64_Rela),
sizeof(Elf64_Rela), relacmp, relaswap);
- relocs += count_relocs((void *)sechdrs[i].sh_addr,
+ sec_relocs = count_relocs((void *)sechdrs[i].sh_addr,
sechdrs[i].sh_size
/ sizeof(Elf64_Rela));
How about also capturing 'sec_relocs' in 'struct mod_arch_specific'? (2)
That will help simplify a lot of the calculations here and elsewhere.
Note that there are many other places where the number of stubs is
derived looking at 'sh_size', which is incorrect since we now have klp
stubs as well (create_ftrace_stub() for instance).
+ relocs += sec_relocs;
+#ifdef CONFIG_LIVEPATCH
+ if (sechdrs[i].sh_flags & SHF_RELA_LIVEPATCH)
+ klp_relocs += sec_relocs;
+#endif
If a module has SHF_RELA_LIVEPATCH, but the kernel is compiled without
CONFIG_LIVEPATCH, should we refuse to load the kernel module?
Yes, the module load will fail.
You might want to consider removing the above #ifdef and processing some
of these flags regardless of CONFIG_LIVEPATCH.
ifdef guard, can be replaced with check for SHF_RELA_LIVEPATCH in
section flag.
}
}
@@ -273,6 +305,15 @@ static unsigned long get_stubs_size(const Elf64_Ehdr *hdr,
relocs++;
#endif
+ relocs -= klp_relocs;
+#ifdef CONFIG_LIVEPATCH
+ me->arch.klp_relocs = klp_relocs;
+
+ pr_debug("Looks like a total of %lu stubs, (%lu) livepatch stubs, max\n",
^^^^^
(%lu livepatch stubs)
Just wondering why the brackets are the way they are...
Makes it better to use the brackets like you suggested.
+ relocs, klp_relocs);
+ return (relocs * sizeof(struct ppc64_stub_entry) +
+ klp_relocs * sizeof(struct ppc64le_klp_stub_entry));
+#endif
pr_debug("Looks like a total of %lu stubs, max\n", relocs);
return relocs * sizeof(struct ppc64_stub_entry);
}
[...]
+#ifdef CONFIG_LIVEPATCH
+static unsigned long klp_stub_for_addr(const Elf64_Shdr *sechdrs,
+ unsigned long addr,
+ struct module *me)
+{
+ struct ppc64le_klp_stub_entry *klp_stubs;
+ unsigned int num_klp_stubs = me->arch.klp_relocs;
+ unsigned int i, num_stubs;
+
+ num_stubs = (sechdrs[me->arch.stubs_section].sh_size -
+ (num_klp_stubs * sizeof(*klp_stubs))) /
+ sizeof(struct ppc64_stub_entry);
(2) This can be simplified if we have me->arch.sec_relocs.
Having it will make the calculation look simple:
num_stubs = (me->arch.sec_relocs * size(struct ppc64_stub_entry).
+
+ /*
+ * Create livepatch stubs after the regular stubs.
+ */
+ klp_stubs = (void *)sechdrs[me->arch.stubs_section].sh_addr +
+ (num_stubs * sizeof(struct ppc64_stub_entry));
+ for (i = 0; stub_func_addr(klp_stubs[i].funcdata); i++) {
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
(1) This needs us to allocate one additional stub.
Good catch, yes there should an extra stub.
--
cheers,
Kamalesh.
--
To unsubscribe from this list: send the line "unsubscribe live-patching" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html