mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Andre Przywara <andre.przywara@arm.com>
To: will.deacon@arm.com
Cc: catalin.marinas@arm.com, linux-arm-kernel@lists.infradead.org,
	linux-kernel@vger.kernel.org
Subject: [PATCH] arm64: add module support for alternatives fixups
Date: Fri, 28 Nov 2014 13:40:45 +0000	[thread overview]
Message-ID: <1417182045-7858-1-git-send-email-andre.przywara@arm.com> (raw)
In-Reply-To: <20141125152954.GF8541@arm.com>

Currently the kernel patches all necessary instructions once at boot
time, so modules are not covered by this.
Change the apply_alternatives() function to take a beginning and an
end pointer and introduce a new variant (apply_alternatives_all()) to
cover the existing use case for the static kernel image section.
Add a module_finalize() function to arm64 to check for an
alternatives section in a module and patch only the instructions from
that specific area.
Since that module code is not touched before the module
initialization has ended, we don't need to halt the machine before
doing the patching in the module's code.

Signed-off-by: Andre Przywara <andre.przywara@arm.com>
---
Hi Will,

so this patch make alternatives patching now work with modules. This
required some changes in the core alternatives code, so it would have
looked better when folded in (but it's already too late for this, I
guess). I have tested this quickly with modules with and without
alternatives sections in them, all seems to work fine.
Not sure if this is too much for -next at this time, though, so I
will leave this decision to you.
I will come up with a proper solution for the .exit.text issue later.

Cheers,
Andre.

 arch/arm64/include/asm/alternative.h |    3 ++-
 arch/arm64/kernel/alternative.c      |   29 +++++++++++++++++++++++++----
 arch/arm64/kernel/module.c           |   18 ++++++++++++++++++
 arch/arm64/kernel/smp.c              |    2 +-
 4 files changed, 46 insertions(+), 6 deletions(-)

diff --git a/arch/arm64/include/asm/alternative.h b/arch/arm64/include/asm/alternative.h
index f6d206e..d261f01 100644
--- a/arch/arm64/include/asm/alternative.h
+++ b/arch/arm64/include/asm/alternative.h
@@ -13,7 +13,8 @@ struct alt_instr {
 	u8  alt_len;		/* size of new instruction(s), <= orig_len */
 };
 
-void apply_alternatives(void);
+void apply_alternatives_all(void);
+void apply_alternatives(void *start, size_t length);
 void free_alternatives_memory(void);
 
 #define ALTINSTR_ENTRY(feature)						      \
diff --git a/arch/arm64/kernel/alternative.c b/arch/arm64/kernel/alternative.c
index 5992ea4..f20cd5b 100644
--- a/arch/arm64/kernel/alternative.c
+++ b/arch/arm64/kernel/alternative.c
@@ -28,12 +28,18 @@
 
 extern struct alt_instr __alt_instructions[], __alt_instructions_end[];
 
-static int __apply_alternatives(void *dummy)
+struct alt_region {
+	struct alt_instr *begin;
+	struct alt_instr *end;
+};
+
+static int __apply_alternatives(void *alt_region)
 {
 	struct alt_instr *alt;
+	struct alt_region *region = alt_region;
 	u8 *origptr, *replptr;
 
-	for (alt = __alt_instructions; alt < __alt_instructions_end; alt++) {
+	for (alt = region->begin; alt < region->end; alt++) {
 		if (!cpus_have_cap(alt->cpufeature))
 			continue;
 
@@ -51,10 +57,25 @@ static int __apply_alternatives(void *dummy)
 	return 0;
 }
 
-void apply_alternatives(void)
+void apply_alternatives_all(void)
 {
+	struct alt_region region = {
+		.begin	= __alt_instructions,
+		.end	= __alt_instructions_end,
+	};
+
 	/* better not try code patching on a live SMP system */
-	stop_machine(__apply_alternatives, NULL, NULL);
+	stop_machine(__apply_alternatives, &region, NULL);
+}
+
+void apply_alternatives(void *start, size_t length)
+{
+	struct alt_region region = {
+		.begin	= start,
+		.end	= start + length,
+	};
+
+	__apply_alternatives(&region);
 }
 
 void free_alternatives_memory(void)
diff --git a/arch/arm64/kernel/module.c b/arch/arm64/kernel/module.c
index 1eb1cc9..fd027b1 100644
--- a/arch/arm64/kernel/module.c
+++ b/arch/arm64/kernel/module.c
@@ -26,6 +26,7 @@
 #include <linux/moduleloader.h>
 #include <linux/vmalloc.h>
 #include <asm/insn.h>
+#include <asm/sections.h>
 
 #define	AARCH64_INSN_IMM_MOVNZ		AARCH64_INSN_IMM_MAX
 #define	AARCH64_INSN_IMM_MOVK		AARCH64_INSN_IMM_16
@@ -394,3 +395,20 @@ overflow:
 	       me->name, (int)ELF64_R_TYPE(rel[i].r_info), val);
 	return -ENOEXEC;
 }
+
+int module_finalize(const Elf_Ehdr *hdr,
+		    const Elf_Shdr *sechdrs,
+		    struct module *me)
+{
+	const Elf_Shdr *s, *se;
+	const char *secstrs = (void *)hdr + sechdrs[hdr->e_shstrndx].sh_offset;
+
+	for (s = sechdrs, se = sechdrs + hdr->e_shnum; s < se; s++) {
+		if (strcmp(".altinstructions", secstrs + s->sh_name) == 0) {
+			apply_alternatives((void *)s->sh_addr, s->sh_size);
+			return 0;
+		}
+	}
+
+	return 0;
+}
diff --git a/arch/arm64/kernel/smp.c b/arch/arm64/kernel/smp.c
index 0ef8789..7ae6ee0 100644
--- a/arch/arm64/kernel/smp.c
+++ b/arch/arm64/kernel/smp.c
@@ -310,7 +310,7 @@ void cpu_die(void)
 void __init smp_cpus_done(unsigned int max_cpus)
 {
 	pr_info("SMP: Total of %d processors activated.\n", num_online_cpus());
-	apply_alternatives();
+	apply_alternatives_all();
 }
 
 void __init smp_prepare_boot_cpu(void)
-- 
1.7.9.5


      reply	other threads:[~2014-11-28 13:41 UTC|newest]

Thread overview: 11+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-11-14 15:54 [PATCH 0/6] arm64: alternatives runtime patching Andre Przywara
2014-11-14 15:54 ` [PATCH 1/6] arm64: add cpu_capabilities bitmap Andre Przywara
2014-11-14 15:54 ` [PATCH 2/6] arm64: add alternative runtime patching Andre Przywara
2014-11-14 15:54 ` [PATCH 3/6] arm64: detect silicon revisions and set cap bits accordingly Andre Przywara
2014-11-14 15:54 ` [PATCH 4/6] arm64: add Cortex-A53 cache errata workaround Andre Przywara
2014-11-14 15:54 ` [PATCH 5/6] arm64: add Cortex-A57 erratum 832075 workaround Andre Przywara
2014-11-14 15:54 ` [PATCH 6/6] arm64: protect alternatives workarounds with Kconfig options Andre Przywara
2014-11-14 16:20 ` [PATCH 0/6] arm64: alternatives runtime patching Arnd Bergmann
2014-11-14 16:31   ` Catalin Marinas
2014-11-25 15:29 ` Will Deacon
2014-11-28 13:40   ` Andre Przywara [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1417182045-7858-1-git-send-email-andre.przywara@arm.com \
    --to=andre.przywara@arm.com \
    --cc=catalin.marinas@arm.com \
    --cc=linux-arm-kernel@lists.infradead.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=will.deacon@arm.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®