public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
From: Mathieu Desnoyers <mathieu.desnoyers@polymtl.ca>
To: Ingo Molnar <mingo@elte.hu>, linux-kernel@vger.kernel.org
Cc: Mathieu Desnoyers <mathieu.desnoyers@polymtl.ca>
Subject: [RFC patch 26/27] Immediate Values - Jump
Date: Wed, 16 Apr 2008 17:34:52 -0400	[thread overview]
Message-ID: <20080416213557.859844730@polymtl.ca> (raw)
In-Reply-To: 20080416213426.298498397@polymtl.ca

[-- Attachment #1: immediate-values-jump.patch --]
[-- Type: text/plain, Size: 18684 bytes --]

Adds a new imv_cond() macro to declare a byte read that is meant to be embedded
in unlikely(imv_cond(var)), so the kernel can dynamically detect patterns such
as mov, test, jne or mov, test, je and patch it with nops and a jump.

Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@polymtl.ca>
---
 arch/x86/kernel/immediate.c     |  381 ++++++++++++++++++++++++++++++++--------
 include/asm-powerpc/immediate.h |    2 
 include/asm-x86/immediate.h     |   34 +++
 include/linux/immediate.h       |   11 -
 kernel/immediate.c              |    6 
 5 files changed, 359 insertions(+), 75 deletions(-)

Index: linux-2.6-lttng/include/asm-x86/immediate.h
===================================================================
--- linux-2.6-lttng.orig/include/asm-x86/immediate.h	2008-04-16 14:04:47.000000000 -0400
+++ linux-2.6-lttng/include/asm-x86/immediate.h	2008-04-16 14:19:13.000000000 -0400
@@ -20,6 +20,7 @@ struct __imv {
 				 * Pointer to the memory location of the
 				 * immediate value within the instruction.
 				 */
+	int  jmp_off;		/* offset for jump target */
 	unsigned char size;	/* Type size. */
 	unsigned char insn_size;/* Instruction size. */
 } __attribute__ ((packed));
@@ -57,6 +58,7 @@ struct __imv {
 				".previous\n\t"				\
 				".section __imv,\"aw\",@progbits\n\t"	\
 				_ASM_PTR "%c1, (3f)-%c2\n\t"		\
+				".int 0\n\t"				\
 				".byte %c2, (2b-1b)\n\t"		\
 				".previous\n\t"				\
 				"mov $0,%0\n\t"				\
@@ -74,6 +76,7 @@ struct __imv {
 				".previous\n\t"				\
 				".section __imv,\"aw\",@progbits\n\t"	\
 				_ASM_PTR "%c1, (3f)-%c2\n\t"		\
+				".int 0\n\t"				\
 				".byte %c2, (2b-1b)\n\t"		\
 				".previous\n\t"				\
 				".org . + ((-.-(2b-1b)) & (%c2-1)), 0x90\n\t" \
@@ -95,6 +98,7 @@ struct __imv {
 				".previous\n\t"				\
 				".section __imv,\"aw\",@progbits\n\t"	\
 				_ASM_PTR "%c1, (3f)-%c2\n\t"		\
+				".int 0\n\t"				\
 				".byte %c2, (2b-1b)\n\t"		\
 				".previous\n\t"				\
 				".org . + ((-.-(2b-1b)) & (%c2-1)), 0x90\n\t" \
@@ -108,6 +112,34 @@ struct __imv {
 		value;							\
 	})
 
-extern int arch_imv_update(const struct __imv *imv, int early);
+/*
+ * Uses %al.
+ * size is 0.
+ * Use in if (unlikely(imv_cond(var)))
+ * Given a char as argument.
+ */
+#define imv_cond(name)							\
+	({								\
+		__typeof__(name##__imv) value;				\
+		BUILD_BUG_ON(sizeof(value) > 1);			\
+		asm (".section __discard,\"\",@progbits\n\t"		\
+			"1:\n\t"					\
+			"mov $0,%0\n\t"					\
+			"2:\n\t"					\
+			".previous\n\t"					\
+			".section __imv,\"aw\",@progbits\n\t"		\
+			_ASM_PTR "%c1, (3f)-1\n\t"			\
+			".int 0\n\t"					\
+			".byte %c2, (2b-1b)\n\t"			\
+			".previous\n\t"					\
+			"mov $0,%0\n\t"					\
+			"3:\n\t"					\
+			: "=a" (value)					\
+			: "i" (&name##__imv),				\
+			  "i" (0));					\
+		value;							\
+	})
+
+extern int arch_imv_update(struct __imv *imv, int early);
 
 #endif /* _ASM_X86_IMMEDIATE_H */
Index: linux-2.6-lttng/arch/x86/kernel/immediate.c
===================================================================
--- linux-2.6-lttng.orig/arch/x86/kernel/immediate.c	2008-04-16 14:04:47.000000000 -0400
+++ linux-2.6-lttng/arch/x86/kernel/immediate.c	2008-04-16 14:06:17.000000000 -0400
@@ -80,13 +80,19 @@
 #include <asm/cacheflush.h>
 
 #define BREAKPOINT_INSTRUCTION  0xcc
+#define JMP_REL8		0xeb
+#define JMP_REL32		0xe9
+#define INSN_NOP1		0x90
+#define INSN_NOP2		0x89, 0xf6
 #define BREAKPOINT_INS_LEN	1
 #define NR_NOPS			10
 
+/*#define DEBUG_IMMEDIATE 1*/
+
 static unsigned long target_after_int3;	/* EIP of the target after the int3 */
 static unsigned long bypass_eip;	/* EIP of the bypass. */
 static unsigned long bypass_after_int3;	/* EIP after the end-of-bypass int3 */
-static unsigned long after_imv;	/*
+static unsigned long after_imv;		/*
 					 * EIP where to resume after the
 					 * single-stepping.
 					 */
@@ -142,6 +148,25 @@ static int imv_notifier(struct notifier_
 
 	if (die_val == DIE_INT3) {
 		if (args->regs->ip == target_after_int3) {
+			/* deal with non-relocatable jmp instructions */
+			switch (*(uint8_t *)bypass_eip) {
+			case JMP_REL8: /* eb cb       jmp rel8 */
+				args->regs->ip +=
+					*(signed char *)(bypass_eip + 1) + 1;
+				return NOTIFY_STOP;
+			case JMP_REL32: /* e9 cw    jmp rel16 (valid on ia32) */
+				  	/* e9 cd    jmp rel32 */
+				args->regs->ip +=
+					*(int *)(bypass_eip + 1) + 4;
+				return NOTIFY_STOP;
+			case INSN_NOP1:
+				/* deal with insertion of nop + jmp_rel32 */
+				if (*((uint8_t *)bypass_eip + 1) == JMP_REL32) {
+					args->regs->ip +=
+						*(int *)(bypass_eip + 2) + 5;
+					return NOTIFY_STOP;
+				}
+			}
 			preempt_disable();
 			args->regs->ip = bypass_eip;
 			return NOTIFY_STOP;
@@ -159,71 +184,107 @@ static struct notifier_block imv_notify 
 	.priority = 0x7fffffff,	/* we need to be notified first */
 };
 
-/**
- * arch_imv_update - update one immediate value
- * @imv: pointer of type const struct __imv to update
- * @early: early boot (1) or normal (0)
- *
- * Update one immediate value. Must be called with imv_mutex held.
+/*
+ * returns -1 if not found
+ * return 0 if found.
  */
-__kprobes int arch_imv_update(const struct __imv *imv, int early)
+static inline int detect_mov_test_jne(uint8_t *addr, uint8_t **opcode,
+		uint8_t **jmp_offset, int *offset_len)
 {
-	int ret;
-	unsigned char opcode_size = imv->insn_size - imv->size;
-	unsigned long insn = imv->imv - opcode_size;
-	unsigned long len;
-	char *vaddr;
-	struct page *pages[1];
-
-#ifdef CONFIG_KPROBES
-	/*
-	 * Fail if a kprobe has been set on this instruction.
-	 * (TODO: we could eventually do better and modify all the (possibly
-	 * nested) kprobes for this site if kprobes had an API for this.
-	 */
-	if (unlikely(!early
-			&& *(unsigned char *)insn == BREAKPOINT_INSTRUCTION)) {
-		printk(KERN_WARNING "Immediate value in conflict with kprobe. "
-				    "Variable at %p, "
-				    "instruction at %p, size %hu\n",
-				    (void *)imv->imv,
-				    (void *)imv->var, imv->size);
-		return -EBUSY;
-	}
-#endif
-
-	/*
-	 * If the variable and the instruction have the same value, there is
-	 * nothing to do.
-	 */
-	switch (imv->size) {
-	case 1:	if (*(uint8_t *)imv->imv
-				== *(uint8_t *)imv->var)
-			return 0;
-		break;
-	case 2:	if (*(uint16_t *)imv->imv
-				== *(uint16_t *)imv->var)
-			return 0;
-		break;
-	case 4:	if (*(uint32_t *)imv->imv
-				== *(uint32_t *)imv->var)
+	printk(KERN_DEBUG "Trying at %p %hx %hx %hx %hx %hx %hx\n",
+		addr, addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]);
+	/* b0 cb    movb cb,%al */
+	if (addr[0] != 0xb0)
+		return -1;
+	/* 84 c0    test %al,%al */
+	if (addr[2] != 0x84 || addr[3] != 0xc0)
+		return -1;
+	printk(KERN_DEBUG "Found test %%al,%%al at %p\n", addr + 2);
+	switch (addr[4]) {
+	case 0x75: /* 75 cb       jne rel8 */
+		printk(KERN_DEBUG "Found jne rel8 at %p\n", addr + 4);
+		*opcode = addr + 4;
+		*jmp_offset = addr + 5;
+		*offset_len = 1;
+		return 0;
+	case 0x0f:
+		switch (addr[5]) {
+		case 0x85:	 /* 0F 85 cw    jne rel16 (valid on ia32) */
+				 /* 0F 85 cd    jne rel32 */
+			printk(KERN_DEBUG "Found jne rel16/32 at %p\n",
+				addr + 5);
+			*opcode = addr + 4;
+			*jmp_offset = addr + 6;
+			*offset_len = 4;
 			return 0;
+		default:
+			return -1;
+		}
 		break;
-#ifdef CONFIG_X86_64
-	case 8:	if (*(uint64_t *)imv->imv
-				== *(uint64_t *)imv->var)
+	default: return -1;
+	}
+}
+
+/*
+ * returns -1 if not found
+ * return 0 if found.
+ */
+static inline int detect_mov_test_je(uint8_t *addr, uint8_t **opcode,
+		uint8_t **jmp_offset, int *offset_len)
+{
+	/* b0 cb    movb cb,%al */
+	if (addr[0] != 0xb0)
+		return -1;
+	/* 84 c0    test %al,%al */
+	if (addr[2] != 0x84 || addr[3] != 0xc0)
+		return -1;
+	printk(KERN_DEBUG "Found test %%al,%%al at %p\n", addr + 2);
+	switch (addr[4]) {
+	case 0x74: /* 74 cb       je rel8 */
+		printk(KERN_DEBUG "Found je rel8 at %p\n", addr + 4);
+		*opcode = addr + 4;
+		*jmp_offset = addr + 5;
+		*offset_len = 1;
+		return 0;
+	case 0x0f:
+		switch (addr[5]) {
+		case 0x84:	 /* 0F 84 cw    je rel16 (valid on ia32) */
+				 /* 0F 84 cd    je rel32 */
+			printk(KERN_DEBUG "Found je rel16/32 at %p\n",
+				addr + 5);
+			*opcode = addr + 4;
+			*jmp_offset = addr + 6;
+			*offset_len = 4;
 			return 0;
+		default:
+			return -1;
+		}
 		break;
-#endif
-	default:return -EINVAL;
+	default: return -1;
 	}
+}
+
+static int static_early;
 
-	if (!early) {
-		/* bypass is 10 bytes long for x86_64 long */
-		WARN_ON(imv->insn_size > 10);
-		_imv_bypass(&bypass_eip, &bypass_after_int3);
+/*
+ * Marked noinline because we prefer to have only one _imv_bypass. Not that it
+ * is required, but there is no need to edit two bypasses.
+ */
+static noinline int replace_instruction_safe(uint8_t *addr, uint8_t *newcode,
+		int size)
+{
+	char *vaddr;
+	struct page *pages[1];
+	int len;
+	int ret;
+
+	/* bypass is 10 bytes long for x86_64 long */
+	WARN_ON(size > 10);
+
+	_imv_bypass(&bypass_eip, &bypass_after_int3);
 
-		after_imv = imv->imv + imv->size;
+	if (!static_early) {
+		after_imv = (unsigned long)addr + size;
 
 		/*
 		 * Using the _early variants because nobody is executing the
@@ -238,22 +299,23 @@ __kprobes int arch_imv_update(const stru
 		vaddr = vmap(pages, 1, VM_MAP, PAGE_KERNEL);
 		BUG_ON(!vaddr);
 		text_poke_early(&vaddr[bypass_eip & ~PAGE_MASK],
-			(void *)insn, imv->insn_size);
+			(void *)addr, size);
 		/*
 		 * Fill the rest with nops.
 		 */
-		len = NR_NOPS - imv->insn_size;
+		len = NR_NOPS - size;
 		add_nops((void *)
-			&vaddr[(bypass_eip & ~PAGE_MASK) + imv->insn_size],
+			&vaddr[(bypass_eip & ~PAGE_MASK) + size],
 			len);
 		vunmap(vaddr);
 
-		target_after_int3 = insn + BREAKPOINT_INS_LEN;
+		target_after_int3 = (unsigned long)addr + BREAKPOINT_INS_LEN;
 		/* register_die_notifier has memory barriers */
 		register_die_notifier(&imv_notify);
-		/* The breakpoint will single-step the bypass */
-		text_poke((void *)insn,
-			((unsigned char[]){BREAKPOINT_INSTRUCTION}), 1);
+		/* The breakpoint will execute the bypass */
+		text_poke((void *)addr,
+			((unsigned char[]){BREAKPOINT_INSTRUCTION}),
+			BREAKPOINT_INS_LEN);
 		/*
 		 * Make sure the breakpoint is set before we continue (visible
 		 * to other CPUs and interrupts).
@@ -265,14 +327,18 @@ __kprobes int arch_imv_update(const stru
 		ret = on_each_cpu(imv_synchronize_core, NULL, 1, 1);
 		BUG_ON(ret != 0);
 
-		text_poke((void *)(insn + opcode_size), (void *)imv->var,
-				imv->size);
+		text_poke((void *)(addr + BREAKPOINT_INS_LEN),
+			&newcode[BREAKPOINT_INS_LEN],
+			size - BREAKPOINT_INS_LEN);
 		/*
 		 * Make sure the value can be seen from other CPUs and
 		 * interrupts.
 		 */
 		wmb();
-		text_poke((void *)insn, (unsigned char *)bypass_eip, 1);
+#ifdef DEBUG_IMMEDIATE
+		mdelay(10);	/* lets the breakpoint for a while */
+#endif
+		text_poke(addr, newcode, BREAKPOINT_INS_LEN);
 		/*
 		 * Wait for all int3 handlers to end (interrupts are disabled in
 		 * int3). This CPU is clearly not in a int3 handler, because
@@ -285,7 +351,184 @@ __kprobes int arch_imv_update(const stru
 		unregister_die_notifier(&imv_notify);
 		/* unregister_die_notifier has memory barriers */
 	} else
-		text_poke_early((void *)imv->imv, (void *)imv->var,
-			imv->size);
+		text_poke_early(addr, newcode, size);
+	return 0;
+}
+
+static int patch_jump_target(struct __imv *imv)
+{
+	uint8_t *opcode, *jmp_offset;
+	int offset_len;
+	int mov_test_j_found = 0;
+
+	if(!detect_mov_test_jne((uint8_t *)imv->imv - 1,
+			&opcode, &jmp_offset, &offset_len)) {
+		imv->insn_size = 1;	/* positive logic */
+		mov_test_j_found = 1;
+	} else if(!detect_mov_test_je((uint8_t *)imv->imv - 1,
+			&opcode, &jmp_offset, &offset_len)) {
+		imv->insn_size = 0;	/* negative logic */
+		mov_test_j_found = 1;
+	}
+
+	if (mov_test_j_found) {
+		int logicvar = imv->insn_size ? imv->var : !imv->var;
+		int newoff;
+
+		if (offset_len == 1) {
+			imv->jmp_off = *(signed char *)jmp_offset;
+			/* replace with JMP_REL8 opcode. */
+			replace_instruction_safe(opcode,
+				((unsigned char[]){ JMP_REL8,
+				(logicvar ? (signed char)imv->jmp_off : 0) }),
+				2);
+		} else {
+			/* replace with nop and JMP_REL16/32 opcode.
+			 * It's ok to shrink an instruction, never ok to
+			 * grow it afterward. */
+			imv->jmp_off = *(int *)jmp_offset;
+			newoff = logicvar ? (int)imv->jmp_off : 0;
+			replace_instruction_safe(opcode,
+				((unsigned char[]){ INSN_NOP1, JMP_REL32,
+				((unsigned char *)&newoff)[0],
+				((unsigned char *)&newoff)[1],
+				((unsigned char *)&newoff)[2],
+				((unsigned char *)&newoff)[3] }),
+				6);
+		}
+		/* now we can get rid of the movb */
+		replace_instruction_safe((uint8_t *)imv->imv - 1,
+			((unsigned char[]){ INSN_NOP2 }),
+			2);
+		/* now we can get rid of the testb */
+		replace_instruction_safe((uint8_t *)imv->imv + 1,
+			((unsigned char[]){ INSN_NOP2 }),
+			2);
+		/* remember opcode + 1 to enable the JMP_REL patching */
+		if (offset_len == 1)
+			imv->imv = (unsigned long)opcode + 1;
+		else
+			imv->imv = (unsigned long)opcode + 2;	/* skip nop */
+		return 0;
+
+	}
+
+	if (*((uint8_t *)imv->imv - 1) == JMP_REL8) {
+		int logicvar = imv->insn_size ? imv->var : !imv->var;
+
+		printk(KERN_DEBUG "Found JMP_REL8 at %p\n",
+			((uint8_t *)imv->imv - 1));
+		replace_instruction_safe((uint8_t *)imv->imv - 1,
+			((unsigned char[]){ JMP_REL8,
+			(logicvar ? (signed char)imv->jmp_off : 0) }),
+			2);
+		return 0;
+	}
+
+	if (*((uint8_t *)imv->imv - 1) == JMP_REL32) {
+		int logicvar = imv->insn_size ? imv->var : !imv->var;
+		int newoff = logicvar ? (int)imv->jmp_off : 0;
+
+		printk(KERN_DEBUG "Found JMP_REL32 at %p, update with %x\n",
+			((uint8_t *)imv->imv - 1), newoff);
+		replace_instruction_safe((uint8_t *)imv->imv - 1,
+			((unsigned char[]){ JMP_REL32,
+			((unsigned char *)&newoff)[0],
+			((unsigned char *)&newoff)[1],
+			((unsigned char *)&newoff)[2],
+			((unsigned char *)&newoff)[3] }),
+			5);
+		return 0;
+	}
+
+	/* Nothing known found. */
+	return -1;
+}
+
+/**
+ * arch_imv_update - update one immediate value
+ * @imv: pointer of type const struct __imv to update
+ * @early: early boot (1) or normal (0)
+ *
+ * Update one immediate value. Must be called with imv_mutex held.
+ */
+__kprobes int arch_imv_update(struct __imv *imv, int early)
+{
+	int ret;
+	uint8_t buf[10];
+	unsigned long insn, opcode_size;
+
+	static_early = early;
+
+	/*
+	 * If imv_cond is encountered, try to patch it with
+	 * patch_jump_target. Continue with normal immediate values if the area
+	 * surrounding the instruction is not as expected.
+	 */
+	if (imv->size == 0) {
+		ret = patch_jump_target(imv);
+		if (ret) {
+#ifdef DEBUG_IMMEDIATE
+			static int nr_fail;
+			printk("Jump target fallback at %lX, nr fail %d\n",
+				imv->imv, ++nr_fail);
+#endif
+			imv->size = 1;
+		} else {
+#ifdef DEBUG_IMMEDIATE
+			static int nr_success;
+			printk("Jump target at %lX, nr success %d\n",
+				imv->imv, ++nr_success);
+#endif
+			return 0;
+		}
+	}
+
+	opcode_size = imv->insn_size - imv->size;
+	insn = imv->imv - opcode_size;
+
+#ifdef CONFIG_KPROBES
+	/*
+	 * Fail if a kprobe has been set on this instruction.
+	 * (TODO: we could eventually do better and modify all the (possibly
+	 * nested) kprobes for this site if kprobes had an API for this.
+	 */
+	if (unlikely(!early
+			&& *(unsigned char *)insn == BREAKPOINT_INSTRUCTION)) {
+		printk(KERN_WARNING "Immediate value in conflict with kprobe. "
+				    "Variable at %p, "
+				    "instruction at %p, size %hu\n",
+				    (void *)imv->var,
+				    (void *)imv->imv, imv->size);
+		return -EBUSY;
+	}
+#endif
+
+	/*
+	 * If the variable and the instruction have the same value, there is
+	 * nothing to do.
+	 */
+	switch (imv->size) {
+	case 1:	if (*(uint8_t *)imv->imv == *(uint8_t *)imv->var)
+			return 0;
+		break;
+	case 2:	if (*(uint16_t *)imv->imv == *(uint16_t *)imv->var)
+			return 0;
+		break;
+	case 4:	if (*(uint32_t *)imv->imv == *(uint32_t *)imv->var)
+			return 0;
+		break;
+#ifdef CONFIG_X86_64
+	case 8:	if (*(uint64_t *)imv->imv == *(uint64_t *)imv->var)
+			return 0;
+		break;
+#endif
+	default:return -EINVAL;
+	}
+
+	memcpy(buf, (uint8_t *)insn, opcode_size);
+	memcpy(&buf[opcode_size], (void *)imv->var, imv->size);
+	replace_instruction_safe((uint8_t *)insn, buf, imv->insn_size);
+
 	return 0;
 }
Index: linux-2.6-lttng/include/linux/immediate.h
===================================================================
--- linux-2.6-lttng.orig/include/linux/immediate.h	2008-04-16 14:04:47.000000000 -0400
+++ linux-2.6-lttng/include/linux/immediate.h	2008-04-16 14:04:48.000000000 -0400
@@ -33,8 +33,7 @@
  * Internal update functions.
  */
 extern void core_imv_update(void);
-extern void imv_update_range(const struct __imv *begin,
-	const struct __imv *end);
+extern void imv_update_range(struct __imv *begin, struct __imv *end);
 extern void imv_unref_core_init(void);
 extern void imv_unref(struct __imv *begin, struct __imv *end, void *start,
 		unsigned long size);
@@ -54,6 +53,14 @@ extern void imv_unref(struct __imv *begi
 #define imv_read(name)			_imv_read(name)
 
 /**
+ * imv_cond - read immediate variable use as condition for if()
+ * @name: immediate value name
+ *
+ * Reads the value of @name.
+ */
+#define imv_cond			_imv_read(name)
+
+/**
  * imv_set - set immediate variable (with locking)
  * @name: immediate value name
  * @i: required value
Index: linux-2.6-lttng/kernel/immediate.c
===================================================================
--- linux-2.6-lttng.orig/kernel/immediate.c	2008-04-16 14:04:47.000000000 -0400
+++ linux-2.6-lttng/kernel/immediate.c	2008-04-16 14:04:48.000000000 -0400
@@ -43,10 +43,10 @@ static DEFINE_MUTEX(imv_mutex);
  *
  * Updates a range of immediates.
  */
-void imv_update_range(const struct __imv *begin,
-		const struct __imv *end)
+void imv_update_range(struct __imv *begin,
+		struct __imv *end)
 {
-	const struct __imv *iter;
+	struct __imv *iter;
 	int ret;
 	for (iter = begin; iter < end; iter++) {
 		mutex_lock(&imv_mutex);
Index: linux-2.6-lttng/include/asm-powerpc/immediate.h
===================================================================
--- linux-2.6-lttng.orig/include/asm-powerpc/immediate.h	2008-04-16 14:04:47.000000000 -0400
+++ linux-2.6-lttng/include/asm-powerpc/immediate.h	2008-04-16 14:04:48.000000000 -0400
@@ -68,6 +68,8 @@ struct __imv {
 		value;							\
 	})
 
+#define imv_cond(name)	imv_read(name)
+
 extern int arch_imv_update(const struct __imv *imv, int early);
 
 #endif /* _ASM_POWERPC_IMMEDIATE_H */

-- 
Mathieu Desnoyers
Computer Engineering Ph.D. Student, Ecole Polytechnique de Montreal
OpenPGP key fingerprint: 8CD5 52C3 8E3C 4140 715F  BA06 3F25 A8FE 3BAE 9A68

  parent reply	other threads:[~2008-04-16 21:37 UTC|newest]

Thread overview: 43+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2008-04-16 21:34 [RFC patch 00/27] Jump-based NMI-safe immediate values and markers for sched-devel.git Mathieu Desnoyers
2008-04-16 21:34 ` [RFC patch 01/27] From: Adrian Bunk <bunk@kernel.org> Mathieu Desnoyers
2008-04-16 21:34 ` [RFC patch 02/27] x86 NMI-safe INT3 and Page Fault Mathieu Desnoyers
2008-04-16 21:34 ` [RFC patch 03/27] Check for breakpoint in text_poke to eliminate bug_on Mathieu Desnoyers
2008-04-16 21:34 ` [RFC patch 04/27] Kprobes - use a mutex to protect the instruction pages list Mathieu Desnoyers
2008-04-16 21:34 ` [RFC patch 05/27] Kprobes - do not use kprobes mutex in arch code Mathieu Desnoyers
2008-04-16 21:34 ` [RFC patch 06/27] Kprobes - declare kprobe_mutex static Mathieu Desnoyers
2008-04-16 21:34 ` [RFC patch 07/27] Text Edit Lock - Architecture Independent Code Mathieu Desnoyers
2008-04-16 21:34 ` [RFC patch 08/27] Text Edit Lock - kprobes architecture independent support Mathieu Desnoyers
2008-04-16 21:34 ` [RFC patch 09/27] Add all cpus option to stop machine run Mathieu Desnoyers
2008-04-16 21:34 ` [RFC patch 10/27] Immediate Values - Architecture Independent Code Mathieu Desnoyers
2008-04-16 21:34 ` [RFC patch 11/27] Immediate Values - Kconfig menu in EMBEDDED Mathieu Desnoyers
2008-04-16 21:34 ` [RFC patch 12/27] Immediate Values - x86 Optimization Mathieu Desnoyers
2008-04-16 21:34 ` [RFC patch 13/27] Add text_poke and sync_core to powerpc Mathieu Desnoyers
2008-04-16 21:34 ` [RFC patch 14/27] Immediate Values - Powerpc Optimization Mathieu Desnoyers
2008-04-16 21:34 ` [RFC patch 15/27] Immediate Values - Documentation Mathieu Desnoyers
2008-04-17  9:52   ` KOSAKI Motohiro
2008-04-17 10:36     ` Adrian Bunk
2008-04-17 12:56       ` Mathieu Desnoyers
2008-04-17 12:17     ` [RFC patch 15/27] Immediate Values - Documentation (updated) Mathieu Desnoyers
2008-04-18  2:27       ` KOSAKI Motohiro
2008-04-16 21:34 ` [RFC patch 16/27] Immediate Values Support init Mathieu Desnoyers
2008-04-19 11:04   ` KOSAKI Motohiro
2008-04-19 13:24     ` Mathieu Desnoyers
2008-04-19 14:06       ` KOSAKI Motohiro
2008-04-16 21:34 ` [RFC patch 17/27] Scheduler Profiling - Use Immediate Values Mathieu Desnoyers
2008-04-16 21:34 ` [RFC patch 18/27] Markers - remove extra format argument Mathieu Desnoyers
2008-04-16 21:34 ` [RFC patch 19/27] Markers - define non optimized marker Mathieu Desnoyers
2008-04-16 21:34 ` [RFC patch 20/27] Immediate Values - Move Kprobes x86 restore_interrupt to kdebug.h Mathieu Desnoyers
2008-04-16 21:34 ` [RFC patch 21/27] Add __discard section to x86 Mathieu Desnoyers
2008-04-16 21:34 ` [RFC patch 22/27] Immediate Values - x86 Optimization NMI and MCE support Mathieu Desnoyers
2008-04-16 21:34 ` [RFC patch 23/27] Immediate Values - Powerpc Optimization NMI " Mathieu Desnoyers
2008-04-16 23:09   ` Paul Mackerras
2008-04-16 23:33     ` Mathieu Desnoyers
2008-04-17  0:35       ` Paul Mackerras
2008-04-17  1:24         ` Mathieu Desnoyers
2008-04-19 23:40           ` Paul E. McKenney
2008-04-16 21:34 ` [RFC patch 24/27] Immediate Values Use Arch NMI and MCE Support Mathieu Desnoyers
2008-04-16 21:34 ` [RFC patch 25/27] Linux Kernel Markers - Use Immediate Values Mathieu Desnoyers
2008-04-16 21:34 ` Mathieu Desnoyers [this message]
2008-04-19 11:41   ` [RFC patch 26/27] Immediate Values - Jump KOSAKI Motohiro
2008-04-19 13:25     ` Mathieu Desnoyers
2008-04-16 21:34 ` [RFC patch 27/27] Markers use imv jump Mathieu Desnoyers

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20080416213557.859844730@polymtl.ca \
    --to=mathieu.desnoyers@polymtl.ca \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mingo@elte.hu \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox