#define DPRINTK(fmt, args...) \ do { \ if (debug_alternative) \
printk(KERN_DEBUG "%s: " fmt "\n", __func__, ##args); \
} while (0)
#define DUMP_WORDS(buf, count, fmt, args...) \ do { \ if (unlikely(debug_alternative)) { \ int _j; \ union loongarch_instruction *_buf = buf; \
\ if (!(count)) \ break; \
\
printk(KERN_DEBUG fmt, ##args); \ for (_j = 0; _j < count - 1; _j++) \
printk(KERN_CONT "<%08x> ", _buf[_j].word); \
printk(KERN_CONT "<%08x>\n", _buf[_j].word); \
} \
} while (0)
/* Use this to add nops to a buffer, then text_poke the whole buffer. */ staticvoid __init_or_module add_nops(union loongarch_instruction *insn, int count)
{ while (count--) {
insn->word = INSN_NOP;
insn++;
}
}
/* Is the jump addr in local .altinstructions */ staticinlinebool in_alt_jump(unsignedlong jump, void *start, void *end)
{ return jump >= (unsignedlong)start && jump < (unsignedlong)end;
}
staticvoid __init_or_module recompute_jump(union loongarch_instruction *buf, union loongarch_instruction *dest, union loongarch_instruction *src, void *start, void *end)
{ unsignedint si, si_l, si_h; unsignedlong cur_pc, jump_addr, pc; long offset;
cur_pc = (unsignedlong)src;
pc = (unsignedlong)dest;
si = src->reg2i16_format.immediate; switch (src->reg2i16_format.opcode) { case beq_op: case bne_op: case blt_op: case bge_op: case bltu_op: case bgeu_op:
jump_addr = cur_pc + sign_extend64(si << 2, 17); if (in_alt_jump(jump_addr, start, end)) return;
offset = jump_addr - pc;
BUG_ON(offset < -SZ_128K || offset >= SZ_128K);
offset >>= 2;
buf->reg2i16_format.immediate = offset; return;
}
}
staticint __init_or_module copy_alt_insns(union loongarch_instruction *buf, union loongarch_instruction *dest, union loongarch_instruction *src, int nr)
{ int i;
for (i = 0; i < nr; i++) {
buf[i].word = src[i].word;
if (is_pc_ins(&src[i])) {
pr_err("Not support pcrel instruction at present!"); return -EINVAL;
}
/* * text_poke_early - Update instructions on a live kernel at boot time * * When you use this code to patch more than one byte of an instruction * you need to make sure that other CPUs cannot execute this code in parallel. * Also no thread must be currently preempted in the middle of these * instructions. And on the local CPU you need to be protected again NMI or MCE * handlers seeing an inconsistent instruction while you patch.
*/ staticvoid *__init_or_module text_poke_early(union loongarch_instruction *insn, union loongarch_instruction *buf, unsignedint nr)
{ int i; unsignedlong flags;
local_irq_save(flags);
for (i = 0; i < nr; i++)
insn[i].word = buf[i].word;
/* * Replace instructions with better alternatives for this CPU type. This runs * before SMP is initialized to avoid SMP problems with self modifying code. * This implies that asymmetric systems where APs have less capabilities than * the boot processor are not handled. Tough. Make sure you disable such * features by hand.
*/ void __init_or_module apply_alternatives(struct alt_instr *start, struct alt_instr *end)
{ struct alt_instr *a; unsignedint nr_instr, nr_repl, nr_insnbuf; union loongarch_instruction *instr, *replacement; union loongarch_instruction insnbuf[MAX_PATCH_SIZE];
DPRINTK("alt table %px, -> %px", start, end); /* * The scan order should be from start to end. A later scanned * alternative code can overwrite previously scanned alternative code. * Some kernel functions (e.g. memcpy, memset, etc) use this order to * patch code. * * So be careful if you want to change the scan order to any other * order.
*/ for (a = start; a < end; a++) {
nr_insnbuf = 0;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.