@@ -6,7 +6,7 @@ subdir-y += mm
subdir-$(CONFIG_XENOPROF) += oprofile
subdir-y += x86_64
-obj-bin-y += alternative.init.o
+obj-bin-y += alternative.o
obj-y += apic.o
obj-y += bitops.o
obj-bin-y += bzimage.init.o
@@ -28,7 +28,7 @@
extern struct alt_instr __alt_instructions[], __alt_instructions_end[];
#ifdef K8_NOP1
-static const unsigned char k8nops[] __initconst = {
+static const unsigned char k8nops[] = {
K8_NOP1,
K8_NOP2,
K8_NOP3,
@@ -52,7 +52,7 @@ static const unsigned char * const k8_nops[ASM_NOP_MAX+1] __initconstrel = {
#endif
#ifdef P6_NOP1
-static const unsigned char p6nops[] __initconst = {
+static const unsigned char p6nops[] = {
P6_NOP1,
P6_NOP2,
P6_NOP3,
@@ -75,7 +75,7 @@ static const unsigned char * const p6_nops[ASM_NOP_MAX+1] __initconstrel = {
};
#endif
-static const unsigned char * const *ideal_nops __initdata = k8_nops;
+static const unsigned char * const *ideal_nops = k8_nops;
static int __init mask_nmi_callback(const struct cpu_user_regs *regs, int cpu)
{
@@ -100,7 +100,7 @@ static void __init arch_init_ideal_nops(void)
}
/* Use this to add nops to a buffer, then text_poke the whole buffer. */
-static void __init add_nops(void *insns, unsigned int len)
+static void add_nops(void *insns, unsigned int len)
{
while ( len > 0 )
{
@@ -127,7 +127,7 @@ static void __init add_nops(void *insns, unsigned int len)
*
* This routine is called with local interrupt disabled.
*/
-static void *__init text_poke_early(void *addr, const void *opcode, size_t len)
+static void *text_poke_early(void *addr, const void *opcode, size_t len)
{
memcpy(addr, opcode, len);
sync_core();
@@ -142,15 +142,13 @@ static void *__init text_poke_early(void *addr, const void *opcode, size_t len)
* APs have less capabilities than the boot processor are not handled.
* Tough. Make sure you disable such features by hand.
*/
-static void __init apply_alternatives(struct alt_instr *start, struct alt_instr *end)
+void apply_alternatives_nocheck(struct alt_instr *start, struct alt_instr *end)
{
struct alt_instr *a;
u8 *instr, *replacement;
u8 insnbuf[MAX_PATCH_LEN];
unsigned long cr0 = read_cr0();
- ASSERT(!local_irq_is_enabled());
-
printk(KERN_INFO "alt table %p -> %p\n", start, end);
/* Disable WP to allow application of alternatives to read-only pages. */
@@ -190,6 +188,12 @@ static void __init apply_alternatives(struct alt_instr *start, struct alt_instr
write_cr0(cr0);
}
+void apply_alternatives(struct alt_instr *start, struct alt_instr *end)
+{
+ ASSERT(!local_irq_is_enabled());
+ apply_alternatives_nocheck(start, end);
+}
+
void __init alternative_instructions(void)
{
nmi_callback_t saved_nmi_callback;
@@ -5,10 +5,13 @@
#include <xen/config.h>
#include <xen/types.h>
+#include <asm/nops.h>
+#include <asm/alternative.h>
/* Our replacement function for xen_extra_version. */
const char *xen_hello_world(void)
{
+ alternative(ASM_NOP1, ASM_NOP1, 1);
return "Hello World";
}
@@ -526,8 +526,24 @@ static int prepare_payload(struct payload *payload,
region->ex_end = (struct exception_table_entry *)(sec->load_addr + sec->sec->sh_size);
sort_exception_table(region->ex, region->ex_end);
+
region->priv |= CHECKING_EXCEPTION;
}
+ sec = xsplice_elf_sec_by_name(elf, ".altinstructions");
+ if ( sec )
+ {
+ if ( !sec->sec->sh_size ||
+ (sec->sec->sh_size % sizeof (struct alt_instr)) )
+ {
+ dprintk(XENLOG_DEBUG, "%s%s: Wrong size of .alt_instr (exp:%lu vs %lu)!\n",
+ XSPLICE, elf->name, sizeof (struct alt_instr),
+ sec->sec->sh_size);
+ return -EINVAL;
+ }
+ apply_alternatives_nocheck((struct alt_instr *)sec->load_addr,
+ (struct alt_instr *)(sec->load_addr +
+ sec->sec->sh_size));
+ }
#endif
return 0;
}
@@ -23,6 +23,12 @@ struct alt_instr {
u8 replacementlen; /* length of new instruction, <= instrlen */
};
+/*
+ * An variant to be used on code that can be patched without many checks.
+ */
+extern void apply_alternatives_nocheck(struct alt_instr *start,
+ struct alt_instr *end);
+extern void apply_alternatives(struct alt_instr *start, struct alt_instr *end);
extern void alternative_instructions(void);
#define OLDINSTR(oldinstr) "661:\n\t" oldinstr "\n662:\n"