diff options
author | Helge Deller <deller@gmx.de> | 2019-08-12 19:11:06 +0200 |
---|---|---|
committer | Helge Deller <deller@gmx.de> | 2019-08-12 19:17:39 +0200 |
commit | 82992fc70f98dee091faa926eb5cecadda5c84f4 (patch) | |
tree | 915078a06f9ed8bd736bbd29d52eca237af19b91 /arch/parisc/kernel | |
parent | 83af58f8068ea3f7b3c537c37a30887bfa585069 (diff) |
parisc: Add ALTERNATIVE_CODE() and ALT_COND_RUN_ON_QEMU
The macro ALTERNATIVE_CODE() allows assembly code to patch in a series
of new assembler statements given at a specific start address.
The ALT_COND_RUN_ON_QEMU condition is true if the kernel is started in a
qemu emulation.
Signed-off-by: Helge Deller <deller@gmx.de>
Diffstat (limited to 'arch/parisc/kernel')
-rw-r--r-- | arch/parisc/kernel/alternative.c | 23 |
1 files changed, 17 insertions, 6 deletions
diff --git a/arch/parisc/kernel/alternative.c b/arch/parisc/kernel/alternative.c index ca1f5ca0540a..3c66d5c4d90d 100644 --- a/arch/parisc/kernel/alternative.c +++ b/arch/parisc/kernel/alternative.c @@ -28,7 +28,8 @@ void __init_or_module apply_alternatives(struct alt_instr *start, for (entry = start; entry < end; entry++, index++) { - u32 *from, len, cond, replacement; + u32 *from, cond, replacement; + s32 len; from = (u32 *)((ulong)&entry->orig_offset + entry->orig_offset); len = entry->len; @@ -49,6 +50,8 @@ void __init_or_module apply_alternatives(struct alt_instr *start, continue; if ((cond & ALT_COND_NO_ICACHE) && (cache_info.ic_size != 0)) continue; + if ((cond & ALT_COND_RUN_ON_QEMU) && !running_on_qemu) + continue; /* * If the PDC_MODEL capabilities has Non-coherent IO-PDIR bit @@ -74,11 +77,19 @@ void __init_or_module apply_alternatives(struct alt_instr *start, if (replacement == INSN_NOP && len > 1) replacement = 0xe8000002 + (len-2)*8; /* "b,n .+8" */ - pr_debug("Do %d: Cond 0x%x, Replace %02d instructions @ 0x%px with 0x%08x\n", - index, cond, len, from, replacement); - - /* Replace instruction */ - *from = replacement; + pr_debug("ALTERNATIVE %3d: Cond %2x, Replace %2d instructions to 0x%08x @ 0x%px (%pS)\n", + index, cond, len, replacement, from, from); + + if (len < 0) { + /* Replace multiple instruction by new code */ + u32 *source; + len = -len; + source = (u32 *)((ulong)&entry->replacement + entry->replacement); + memcpy(from, source, 4 * len); + } else { + /* Replace by one instruction */ + *from = replacement; + } applied++; } |