linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Peter Zijlstra <peterz@infradead.org>
To: x86@kernel.org, jpoimboe@redhat.com, andrew.cooper3@citrix.com
Cc: linux-kernel@vger.kernel.org, peterz@infradead.org,
	alexei.starovoitov@gmail.com, ndesaulniers@google.com
Subject: [PATCH 1/9] objtool,x86: Replace alternatives with .retpoline_sites
Date: Wed, 13 Oct 2021 14:22:18 +0200	[thread overview]
Message-ID: <20211013123644.614129149@infradead.org> (raw)
In-Reply-To: 20211013122217.304265366@infradead.org

Instead of writing complete alternatives, simply provide a list of all
the retpoline thunk calls. Then the kernel is free to do with them as
it pleases. Simpler code all-round.

Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
---
 arch/x86/kernel/vmlinux.lds.S       |   12 +++
 arch/x86/lib/retpoline.S            |   42 ------------
 tools/objtool/arch/x86/decode.c     |  126 +++++++-----------------------------
 tools/objtool/elf.c                 |   84 ------------------------
 tools/objtool/include/objtool/elf.h |    1 
 5 files changed, 38 insertions(+), 227 deletions(-)

--- a/arch/x86/kernel/vmlinux.lds.S
+++ b/arch/x86/kernel/vmlinux.lds.S
@@ -273,6 +273,18 @@ SECTIONS
 	}
 
 	/*
+	 * List of instructions that call/jmp/jcc to retpoline thunks
+	 * __x86_indirect_thunk_*(). These instructions can be patched along
+	 * with alternatives, after which the section can be freed.
+	 */
+	. = ALIGN(8);
+	.retpoline_sites : AT(ADDR(.retpoline_sites) - LOAD_OFFSET) {
+		__retpoline_sites = .;
+		*(.retpoline_sites)
+		__retpoline_sites_end = .;
+	}
+
+	/*
 	 * struct alt_inst entries. From the header (alternative.h):
 	 * "Alternative instructions for different CPU types or capabilities"
 	 * Think locking instructions on spinlocks.
--- a/tools/objtool/arch/x86/decode.c
+++ b/tools/objtool/arch/x86/decode.c
@@ -711,121 +711,47 @@ const char *arch_ret_insn(int len)
 	return ret[len-1];
 }
 
-/* asm/alternative.h ? */
-
-#define ALTINSTR_FLAG_INV	(1 << 15)
-#define ALT_NOT(feat)		((feat) | ALTINSTR_FLAG_INV)
-
-struct alt_instr {
-	s32 instr_offset;	/* original instruction */
-	s32 repl_offset;	/* offset to replacement instruction */
-	u16 cpuid;		/* cpuid bit set for replacement */
-	u8  instrlen;		/* length of original instruction */
-	u8  replacementlen;	/* length of new instruction */
-} __packed;
-
-static int elf_add_alternative(struct elf *elf,
-			       struct instruction *orig, struct symbol *sym,
-			       int cpuid, u8 orig_len, u8 repl_len)
+int arch_rewrite_retpolines(struct objtool_file *file)
 {
-	const int size = sizeof(struct alt_instr);
-	struct alt_instr *alt;
+	struct instruction *insn;
 	struct section *sec;
-	Elf_Scn *s;
-
-	sec = find_section_by_name(elf, ".altinstructions");
-	if (!sec) {
-		sec = elf_create_section(elf, ".altinstructions",
-					 SHF_ALLOC, 0, 0);
-
-		if (!sec) {
-			WARN_ELF("elf_create_section");
-			return -1;
-		}
-	}
-
-	s = elf_getscn(elf->elf, sec->idx);
-	if (!s) {
-		WARN_ELF("elf_getscn");
-		return -1;
-	}
+	int idx;
 
-	sec->data = elf_newdata(s);
-	if (!sec->data) {
-		WARN_ELF("elf_newdata");
-		return -1;
+	sec = find_section_by_name(file->elf, ".retpoline_sites");
+	if (sec) {
+		WARN("file already has .retpoline_sites, skipping");
+		return 0;
 	}
 
-	sec->data->d_size = size;
-	sec->data->d_align = 1;
-
-	alt = sec->data->d_buf = malloc(size);
-	if (!sec->data->d_buf) {
-		perror("malloc");
-		return -1;
-	}
-	memset(sec->data->d_buf, 0, size);
+	idx = 0;
+	list_for_each_entry(insn, &file->retpoline_call_list, call_node)
+		idx++;
 
-	if (elf_add_reloc_to_insn(elf, sec, sec->sh.sh_size,
-				  R_X86_64_PC32, orig->sec, orig->offset)) {
-		WARN("elf_create_reloc: alt_instr::instr_offset");
-		return -1;
-	}
+	if (!idx)
+		return 0;
 
-	if (elf_add_reloc(elf, sec, sec->sh.sh_size + 4,
-			  R_X86_64_PC32, sym, 0)) {
-		WARN("elf_create_reloc: alt_instr::repl_offset");
+	sec = elf_create_section(file->elf, ".retpoline_sites", 0,
+				 sizeof(int), idx);
+	if (!sec) {
+		WARN("elf_create_section: .retpoline_sites");
 		return -1;
 	}
 
-	alt->cpuid = bswap_if_needed(cpuid);
-	alt->instrlen = orig_len;
-	alt->replacementlen = repl_len;
-
-	sec->sh.sh_size += size;
-	sec->changed = true;
-
-	return 0;
-}
-
-#define X86_FEATURE_RETPOLINE                ( 7*32+12)
-
-int arch_rewrite_retpolines(struct objtool_file *file)
-{
-	struct instruction *insn;
-	struct reloc *reloc;
-	struct symbol *sym;
-	char name[32] = "";
-
+	idx = 0;
 	list_for_each_entry(insn, &file->retpoline_call_list, call_node) {
 
-		if (insn->type != INSN_JUMP_DYNAMIC &&
-		    insn->type != INSN_CALL_DYNAMIC)
-			continue;
-
-		if (!strcmp(insn->sec->name, ".text.__x86.indirect_thunk"))
-			continue;
-
-		reloc = insn->reloc;
-
-		sprintf(name, "__x86_indirect_alt_%s_%s",
-			insn->type == INSN_JUMP_DYNAMIC ? "jmp" : "call",
-			reloc->sym->name + 21);
-
-		sym = find_symbol_by_name(file->elf, name);
-		if (!sym) {
-			sym = elf_create_undef_symbol(file->elf, name);
-			if (!sym) {
-				WARN("elf_create_undef_symbol");
-				return -1;
-			}
-		}
+		int *site = (int *)sec->data->d_buf + idx;
+		*site = 0;
 
-		if (elf_add_alternative(file->elf, insn, sym,
-					ALT_NOT(X86_FEATURE_RETPOLINE), 5, 5)) {
-			WARN("elf_add_alternative");
+		if (elf_add_reloc_to_insn(file->elf, sec,
+					  idx * sizeof(int),
+					  R_X86_64_PC32,
+					  insn->sec, insn->offset)) {
+			WARN("elf_add_reloc_to_insn: .retpoline_sites");
 			return -1;
 		}
+
+		idx++;
 	}
 
 	return 0;
--- a/tools/objtool/elf.c
+++ b/tools/objtool/elf.c
@@ -740,90 +740,6 @@ static int elf_add_string(struct elf *el
 	return len;
 }
 
-struct symbol *elf_create_undef_symbol(struct elf *elf, const char *name)
-{
-	struct section *symtab, *symtab_shndx;
-	struct symbol *sym;
-	Elf_Data *data;
-	Elf_Scn *s;
-
-	sym = malloc(sizeof(*sym));
-	if (!sym) {
-		perror("malloc");
-		return NULL;
-	}
-	memset(sym, 0, sizeof(*sym));
-
-	sym->name = strdup(name);
-
-	sym->sym.st_name = elf_add_string(elf, NULL, sym->name);
-	if (sym->sym.st_name == -1)
-		return NULL;
-
-	sym->sym.st_info = GELF_ST_INFO(STB_GLOBAL, STT_NOTYPE);
-	// st_other 0
-	// st_shndx 0
-	// st_value 0
-	// st_size 0
-
-	symtab = find_section_by_name(elf, ".symtab");
-	if (!symtab) {
-		WARN("can't find .symtab");
-		return NULL;
-	}
-
-	s = elf_getscn(elf->elf, symtab->idx);
-	if (!s) {
-		WARN_ELF("elf_getscn");
-		return NULL;
-	}
-
-	data = elf_newdata(s);
-	if (!data) {
-		WARN_ELF("elf_newdata");
-		return NULL;
-	}
-
-	data->d_buf = &sym->sym;
-	data->d_size = sizeof(sym->sym);
-	data->d_align = 1;
-	data->d_type = ELF_T_SYM;
-
-	sym->idx = symtab->sh.sh_size / sizeof(sym->sym);
-
-	symtab->sh.sh_size += data->d_size;
-	symtab->changed = true;
-
-	symtab_shndx = find_section_by_name(elf, ".symtab_shndx");
-	if (symtab_shndx) {
-		s = elf_getscn(elf->elf, symtab_shndx->idx);
-		if (!s) {
-			WARN_ELF("elf_getscn");
-			return NULL;
-		}
-
-		data = elf_newdata(s);
-		if (!data) {
-			WARN_ELF("elf_newdata");
-			return NULL;
-		}
-
-		data->d_buf = &sym->sym.st_size; /* conveniently 0 */
-		data->d_size = sizeof(Elf32_Word);
-		data->d_align = 4;
-		data->d_type = ELF_T_WORD;
-
-		symtab_shndx->sh.sh_size += 4;
-		symtab_shndx->changed = true;
-	}
-
-	sym->sec = find_section_by_index(elf, 0);
-
-	elf_add_symbol(elf, sym);
-
-	return sym;
-}
-
 struct section *elf_create_section(struct elf *elf, const char *name,
 				   unsigned int sh_flags, size_t entsize, int nr)
 {
--- a/tools/objtool/include/objtool/elf.h
+++ b/tools/objtool/include/objtool/elf.h
@@ -141,7 +141,6 @@ int elf_write_insn(struct elf *elf, stru
 		   unsigned long offset, unsigned int len,
 		   const char *insn);
 int elf_write_reloc(struct elf *elf, struct reloc *reloc);
-struct symbol *elf_create_undef_symbol(struct elf *elf, const char *name);
 int elf_write(struct elf *elf);
 void elf_close(struct elf *elf);
 



  reply	other threads:[~2021-10-13 12:42 UTC|newest]

Thread overview: 52+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-10-13 12:22 [PATCH 0/9] x86: Rewrite the retpoline rewrite logic Peter Zijlstra
2021-10-13 12:22 ` Peter Zijlstra [this message]
2021-10-13 13:29   ` [PATCH 1/9] objtool,x86: Replace alternatives with .retpoline_sites Borislav Petkov
2021-10-13 20:11   ` Josh Poimboeuf
2021-10-14 15:43     ` Peter Zijlstra
2021-10-13 12:22 ` [PATCH 2/9] x86/retpoline: Remove unused replacement symbols Peter Zijlstra
2021-10-13 12:22 ` [PATCH 3/9] x86/asm: Fix register order Peter Zijlstra
2021-10-13 20:15   ` Josh Poimboeuf
2021-10-13 12:22 ` [PATCH 4/9] x86/alternative: Implement .retpoline_sites support Peter Zijlstra
2021-10-13 14:38   ` Andrew Cooper
2021-10-13 15:12     ` Peter Zijlstra
2021-10-13 17:11       ` Andrew Cooper
2021-10-14 10:05       ` Peter Zijlstra
2021-10-13 20:39   ` Josh Poimboeuf
2021-10-13 21:20     ` Peter Zijlstra
2021-10-13 21:49       ` Josh Poimboeuf
2021-10-13 21:52         ` Josh Poimboeuf
2021-10-13 22:10         ` Peter Zijlstra
2021-10-13 22:47           ` Andrew Cooper
2021-10-13 20:52   ` Josh Poimboeuf
2021-10-13 21:00     ` Peter Zijlstra
2021-10-19 11:37     ` Peter Zijlstra
2021-10-19 16:46       ` Josh Poimboeuf
2021-10-19 16:49         ` Josh Poimboeuf
2021-10-20  8:25           ` Peter Zijlstra
2021-10-20  8:30           ` Peter Zijlstra
2021-10-13 21:11   ` Josh Poimboeuf
2021-10-13 21:43     ` Peter Zijlstra
2021-10-13 22:05       ` Josh Poimboeuf
2021-10-13 22:14         ` Peter Zijlstra
2021-10-15 14:24   ` Borislav Petkov
2021-10-15 16:56     ` Peter Zijlstra
2021-10-18 23:06       ` Alexander Lobakin
2021-10-19  0:25         ` Alexander Lobakin
2021-10-19  9:47           ` Alexander Lobakin
2021-10-19 10:16             ` Peter Zijlstra
2021-10-19 15:37               ` Sami Tolvanen
2021-10-19 18:00                 ` Alexander Lobakin
2021-10-19  9:40         ` Peter Zijlstra
2021-10-19 10:02           ` Peter Zijlstra
2021-10-13 12:22 ` [PATCH 5/9] x86/alternative: Handle Jcc __x86_indirect_thunk_\reg Peter Zijlstra
2021-10-13 20:11   ` Nick Desaulniers
2021-10-13 21:08     ` Peter Zijlstra
2021-10-13 12:22 ` [PATCH 6/9] x86/alternative: Try inline spectre_v2=retpoline,amd Peter Zijlstra
2021-10-13 12:22 ` [PATCH 7/9] x86/alternative: Add debug prints to apply_retpolines() Peter Zijlstra
2021-10-13 12:22 ` [PATCH 8/9] x86,bugs: Unconditionally allow spectre_v2=retpoline,amd Peter Zijlstra
2021-10-13 12:22 ` [PATCH 9/9] bpf,x86: Respect X86_FEATURE_RETPOLINE* Peter Zijlstra
2021-10-13 21:06   ` Josh Poimboeuf
2021-10-13 21:54     ` Peter Zijlstra
2021-10-14  9:46       ` Peter Zijlstra
2021-10-14  9:48         ` Peter Zijlstra
2021-10-20  7:34         ` Peter Zijlstra

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=20211013123644.614129149@infradead.org \
    --to=peterz@infradead.org \
    --cc=alexei.starovoitov@gmail.com \
    --cc=andrew.cooper3@citrix.com \
    --cc=jpoimboe@redhat.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=ndesaulniers@google.com \
    --cc=x86@kernel.org \
    /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;
as well as URLs for NNTP newsgroup(s).