|
|
@@ -662,15 +662,29 @@ void __init alternative_instructions(void)
|
|
|
* handlers seeing an inconsistent instruction while you patch.
|
|
|
*/
|
|
|
void *__init_or_module text_poke_early(void *addr, const void *opcode,
|
|
|
- size_t len)
|
|
|
+ size_t len)
|
|
|
{
|
|
|
unsigned long flags;
|
|
|
- local_irq_save(flags);
|
|
|
- memcpy(addr, opcode, len);
|
|
|
- local_irq_restore(flags);
|
|
|
- sync_core();
|
|
|
- /* Could also do a CLFLUSH here to speed up CPU recovery; but
|
|
|
- that causes hangs on some VIA CPUs. */
|
|
|
+
|
|
|
+ if (boot_cpu_has(X86_FEATURE_NX) &&
|
|
|
+ is_module_text_address((unsigned long)addr)) {
|
|
|
+ /*
|
|
|
+ * Modules text is marked initially as non-executable, so the
|
|
|
+ * code cannot be running and speculative code-fetches are
|
|
|
+ * prevented. Just change the code.
|
|
|
+ */
|
|
|
+ memcpy(addr, opcode, len);
|
|
|
+ } else {
|
|
|
+ local_irq_save(flags);
|
|
|
+ memcpy(addr, opcode, len);
|
|
|
+ local_irq_restore(flags);
|
|
|
+ sync_core();
|
|
|
+
|
|
|
+ /*
|
|
|
+ * Could also do a CLFLUSH here to speed up CPU recovery; but
|
|
|
+ * that causes hangs on some VIA CPUs.
|
|
|
+ */
|
|
|
+ }
|
|
|
return addr;
|
|
|
}
|
|
|
|