[POC 05/12] x86-64: initial ro-after-init patching support

From: Rasmus Villemoes
Date: Wed Oct 17 2018 - 18:34:31 EST


This just sets things up so that the ARCH_HAS_RAI symbol gets selected,
and prepare the arch-specific headers and support functions.

Signed-off-by: Rasmus Villemoes <linux@xxxxxxxxxxxxxxxxxx>
---
arch/x86/Kconfig | 1 +
arch/x86/include/asm/rai.S | 18 ++++++++++++++++++
arch/x86/include/asm/rai.h | 25 ++++++++++++++++++++++++
arch/x86/kernel/Makefile | 1 +
arch/x86/kernel/macros.S | 1 +
arch/x86/kernel/rai.c | 39 ++++++++++++++++++++++++++++++++++++++
6 files changed, 85 insertions(+)
create mode 100644 arch/x86/include/asm/rai.S
create mode 100644 arch/x86/include/asm/rai.h
create mode 100644 arch/x86/kernel/rai.c

diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index 5136a1281870..3f1679f258c9 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -62,6 +62,7 @@ config X86
select ARCH_HAS_MEMBARRIER_SYNC_CORE
select ARCH_HAS_PMEM_API if X86_64
select ARCH_HAS_PTE_SPECIAL
+ select ARCH_HAS_RAI if X86_64
select ARCH_HAS_REFCOUNT
select ARCH_HAS_UACCESS_FLUSHCACHE if X86_64
select ARCH_HAS_UACCESS_MCSAFE if X86_64 && X86_MCE
diff --git a/arch/x86/include/asm/rai.S b/arch/x86/include/asm/rai.S
new file mode 100644
index 000000000000..253d27453416
--- /dev/null
+++ b/arch/x86/include/asm/rai.S
@@ -0,0 +1,18 @@
+#ifdef __ASSEMBLY__
+
+.macro rai_entry type instr instr_end templ templ_end thunk
+ .long \type
+ .long \instr - .
+ .long \instr_end - \instr
+ .long \templ - .
+ .long \templ_end - \templ
+ .long \thunk - .
+.endm
+
+.macro rai_entry_pad start end
+ .ifgt STRUCT_RAI_ENTRY_SIZE-(\end-\start)
+ .skip STRUCT_RAI_ENTRY_SIZE-(\end-\start), 0x00
+ .endif
+.endm
+
+#endif
diff --git a/arch/x86/include/asm/rai.h b/arch/x86/include/asm/rai.h
new file mode 100644
index 000000000000..269d696255b0
--- /dev/null
+++ b/arch/x86/include/asm/rai.h
@@ -0,0 +1,25 @@
+#ifndef _ASM_X86_RAI_H
+#define _ASM_X86_RAI_H
+
+#define STRUCT_RAI_ENTRY_SIZE 24
+
+/* Put the asm macros in a separate file for easier editing. */
+#include <asm/rai.S>
+
+#ifndef __ASSEMBLY__
+
+struct rai_entry {
+ int type; /* RAI_xxx constant */
+ s32 instr_offset; /* member-relative offset to instructions-to-be-patched */
+ s32 instr_len; /* size of area, >= templ_len */
+ s32 templ_offset; /* member-relative offset to template */
+ s32 templ_len; /* length of template */
+ s32 thunk_offset; /* member-relative offset to ool thunk */
+ /* type-specific data follows */
+};
+_Static_assert(sizeof(struct rai_entry) == STRUCT_RAI_ENTRY_SIZE,
+ "please update STRUCT_RAI_ENTRY_SIZE");
+
+#endif /* !__ASSEMBLY */
+
+#endif /* _ASM_X86_RAI_H */
diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile
index 8824d01c0c35..b4dea4e72081 100644
--- a/arch/x86/kernel/Makefile
+++ b/arch/x86/kernel/Makefile
@@ -58,6 +58,7 @@ obj-$(CONFIG_SYSFS) += ksysfs.o
obj-y += bootflag.o e820.o
obj-y += pci-dma.o quirks.o topology.o kdebugfs.o
obj-y += alternative.o i8253.o hw_breakpoint.o
+obj-$(CONFIG_ARCH_HAS_RAI) += rai.o
obj-y += tsc.o tsc_msr.o io_delay.o rtc.o
obj-y += pci-iommu_table.o
obj-y += resource.o
diff --git a/arch/x86/kernel/macros.S b/arch/x86/kernel/macros.S
index 161c95059044..af5672a302d4 100644
--- a/arch/x86/kernel/macros.S
+++ b/arch/x86/kernel/macros.S
@@ -14,3 +14,4 @@
#include <asm/asm.h>
#include <asm/cpufeature.h>
#include <asm/jump_label.h>
+#include <asm/rai.h>
diff --git a/arch/x86/kernel/rai.c b/arch/x86/kernel/rai.c
new file mode 100644
index 000000000000..2c6ff06f7a34
--- /dev/null
+++ b/arch/x86/kernel/rai.c
@@ -0,0 +1,39 @@
+#include <linux/memory.h>
+#include <linux/mutex.h>
+#include <linux/rai.h>
+#include <asm/text-patching.h>
+
+extern struct rai_entry __start_rai_data[];
+extern struct rai_entry __stop_rai_data[];
+
+static void
+rai_patch_one(const struct rai_entry *r)
+{
+ u8 *instr = (u8*)&r->instr_offset + r->instr_offset;
+ u8 *templ = (u8*)&r->templ_offset + r->templ_offset;
+ u8 *thunk = (u8*)&r->thunk_offset + r->thunk_offset;
+
+ switch (r->type) {
+ default:
+ WARN_ONCE(1, "unhandled RAI type %d\n", r->type);
+ return;
+ }
+ text_poke_bp(instr, templ, r->templ_len, thunk);
+}
+
+static void
+rai_patch(const struct rai_entry *start, const struct rai_entry *stop)
+{
+ const struct rai_entry *r;
+
+ for (r = start; r < stop; ++r)
+ rai_patch_one(r);
+}
+
+void
+update_rai_access(void)
+{
+ mutex_lock(&text_mutex);
+ rai_patch(__start_rai_data, __stop_rai_data);
+ mutex_unlock(&text_mutex);
+}
--
2.19.1.6.gbde171bbf5