forked from ValveSoftware/steamos_kernel
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
arm64: add alternative runtime patching
With a blatant copy of some x86 bits we introduce the alternative runtime patching "framework" to arm64. This is quite basic for now and we only provide the functions we need at this time. This is connected to the newly introduced feature bits. Signed-off-by: Andre Przywara <andre.przywara@arm.com> Signed-off-by: Will Deacon <will.deacon@arm.com>
- Loading branch information
Showing
7 changed files
with
139 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
#ifndef __ASM_ALTERNATIVE_ASM_H | ||
#define __ASM_ALTERNATIVE_ASM_H | ||
|
||
#ifdef __ASSEMBLY__ | ||
|
||
.macro altinstruction_entry orig_offset alt_offset feature orig_len alt_len | ||
.word \orig_offset - . | ||
.word \alt_offset - . | ||
.hword \feature | ||
.byte \orig_len | ||
.byte \alt_len | ||
.endm | ||
|
||
#endif /* __ASSEMBLY__ */ | ||
|
||
#endif /* __ASM_ALTERNATIVE_ASM_H */ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
#ifndef __ASM_ALTERNATIVE_H | ||
#define __ASM_ALTERNATIVE_H | ||
|
||
#include <linux/types.h> | ||
#include <linux/stddef.h> | ||
#include <linux/stringify.h> | ||
|
||
struct alt_instr { | ||
s32 orig_offset; /* offset to original instruction */ | ||
s32 alt_offset; /* offset to replacement instruction */ | ||
u16 cpufeature; /* cpufeature bit set for replacement */ | ||
u8 orig_len; /* size of original instruction(s) */ | ||
u8 alt_len; /* size of new instruction(s), <= orig_len */ | ||
}; | ||
|
||
void apply_alternatives(void); | ||
void free_alternatives_memory(void); | ||
|
||
#define ALTINSTR_ENTRY(feature) \ | ||
" .word 661b - .\n" /* label */ \ | ||
" .word 663f - .\n" /* new instruction */ \ | ||
" .hword " __stringify(feature) "\n" /* feature bit */ \ | ||
" .byte 662b-661b\n" /* source len */ \ | ||
" .byte 664f-663f\n" /* replacement len */ | ||
|
||
/* alternative assembly primitive: */ | ||
#define ALTERNATIVE(oldinstr, newinstr, feature) \ | ||
"661:\n\t" \ | ||
oldinstr "\n" \ | ||
"662:\n" \ | ||
".pushsection .altinstructions,\"a\"\n" \ | ||
ALTINSTR_ENTRY(feature) \ | ||
".popsection\n" \ | ||
".pushsection .altinstr_replacement, \"a\"\n" \ | ||
"663:\n\t" \ | ||
newinstr "\n" \ | ||
"664:\n\t" \ | ||
".popsection\n\t" \ | ||
".if ((664b-663b) != (662b-661b))\n\t" \ | ||
" .error \"Alternatives instruction length mismatch\"\n\t"\ | ||
".endif\n" | ||
|
||
#endif /* __ASM_ALTERNATIVE_H */ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
/* | ||
* alternative runtime patching | ||
* inspired by the x86 version | ||
* | ||
* Copyright (C) 2014 ARM Ltd. | ||
* | ||
* This program is free software; you can redistribute it and/or modify | ||
* it under the terms of the GNU General Public License version 2 as | ||
* published by the Free Software Foundation. | ||
* | ||
* This program is distributed in the hope that it will be useful, | ||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
* GNU General Public License for more details. | ||
* | ||
* You should have received a copy of the GNU General Public License | ||
* along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
*/ | ||
|
||
#define pr_fmt(fmt) "alternatives: " fmt | ||
|
||
#include <linux/init.h> | ||
#include <linux/cpu.h> | ||
#include <asm/cacheflush.h> | ||
#include <asm/alternative.h> | ||
#include <asm/cpufeature.h> | ||
#include <linux/stop_machine.h> | ||
|
||
extern struct alt_instr __alt_instructions[], __alt_instructions_end[]; | ||
|
||
static int __apply_alternatives(void *dummy) | ||
{ | ||
struct alt_instr *alt; | ||
u8 *origptr, *replptr; | ||
|
||
for (alt = __alt_instructions; alt < __alt_instructions_end; alt++) { | ||
if (!cpus_have_cap(alt->cpufeature)) | ||
continue; | ||
|
||
BUG_ON(alt->alt_len > alt->orig_len); | ||
|
||
pr_info_once("patching kernel code\n"); | ||
|
||
origptr = (u8 *)&alt->orig_offset + alt->orig_offset; | ||
replptr = (u8 *)&alt->alt_offset + alt->alt_offset; | ||
memcpy(origptr, replptr, alt->alt_len); | ||
flush_icache_range((uintptr_t)origptr, | ||
(uintptr_t)(origptr + alt->alt_len)); | ||
} | ||
|
||
return 0; | ||
} | ||
|
||
void apply_alternatives(void) | ||
{ | ||
/* better not try code patching on a live SMP system */ | ||
stop_machine(__apply_alternatives, NULL, NULL); | ||
} | ||
|
||
void free_alternatives_memory(void) | ||
{ | ||
free_reserved_area(__alt_instructions, __alt_instructions_end, | ||
0, "alternatives"); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters