---
 arch/ia64/Makefile                |    3 -
 arch/ia64/test-module/Makefile    |    7 ++
 arch/ia64/test-module/cmc.c       |   47 +++++++++++++++++
 arch/ia64/test-module/debug.c     |   89 ++++++++++++++++++++++++++++++++
 arch/ia64/test-module/do_dump.c   |   14 +++++
 arch/ia64/test-module/do_hang.c   |   26 +++++++++
 arch/ia64/test-module/do_mca.c    |   21 +++++++
 arch/ia64/test-module/do_panic.c  |   17 ++++++
 arch/ia64/test-module/do_spin.c   |   34 ++++++++++++
 arch/ia64/test-module/kdb_enter.c |   26 +++++++++
 arch/ia64/test-module/measure.c   |   77 ++++++++++++++++++++++++++++
 arch/ia64/test-module/patch.c     |  103 ++++++++++++++++++++++++++++++++++++++
 arch/ia64/test-module/spin.c      |   57 +++++++++++++++++++++
 arch/x86/Makefile                 |    3 -
 arch/x86/test-module/Makefile     |    7 ++
 arch/x86/test-module/cmc.c        |   47 +++++++++++++++++
 arch/x86/test-module/debug.c      |   89 ++++++++++++++++++++++++++++++++
 arch/x86/test-module/do_dump.c    |   14 +++++
 arch/x86/test-module/do_hang.c    |   26 +++++++++
 arch/x86/test-module/do_mca.c     |   21 +++++++
 arch/x86/test-module/do_panic.c   |   17 ++++++
 arch/x86/test-module/do_spin.c    |   34 ++++++++++++
 arch/x86/test-module/kdb_enter.c  |   26 +++++++++
 arch/x86/test-module/measure.c    |   77 ++++++++++++++++++++++++++++
 arch/x86/test-module/patch.c      |  103 ++++++++++++++++++++++++++++++++++++++
 arch/x86/test-module/spin.c       |   57 +++++++++++++++++++++
 26 files changed, 1040 insertions(+), 2 deletions(-)

Index: linux/arch/ia64/Makefile
===================================================================
--- linux.orig/arch/ia64/Makefile	2008-10-27 16:15:41.423595479 -0700
+++ linux/arch/ia64/Makefile	2008-10-27 18:29:21.356697752 -0700
@@ -63,7 +63,8 @@ core-$(CONFIG_IA64_SGI_UV)	+= arch/ia64/
 core-$(CONFIG_KVM) 		+= arch/ia64/kvm/
 core-$(CONFIG_XEN)		+= arch/ia64/xen/
 
-drivers-$(CONFIG_KDB)		+= arch/$(ARCH)/kdb/
+drivers-$(CONFIG_KDB)		+= arch/$(ARCH)/kdb/  \
+				   arch/$(ARCH)/test-module/
 drivers-$(CONFIG_PCI)		+= arch/ia64/pci/
 drivers-$(CONFIG_IA64_HP_SIM)	+= arch/ia64/hp/sim/
 drivers-$(CONFIG_IA64_HP_ZX1)	+= arch/ia64/hp/common/ arch/ia64/hp/zx1/
Index: linux/arch/ia64/test-module/Makefile
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ linux/arch/ia64/test-module/Makefile	2008-10-27 18:29:21.372697420 -0700
@@ -0,0 +1,7 @@
+obj-$(subst $(CONFIG_KDB),y,m)	+= do_mca.o spin.o
+obj-$(subst $(CONFIG_DUMP),y,m) += do_dump.o
+obj-m				+= do_mca.o do_spin.o do_panic.o do_hang.o
+ifdef CONFIG_IA64
+# obj-$(subst $(CONFIG_KDB),y,m)	+= debug.o cmc.o patch.o measure.o
+obj-$(subst $(CONFIG_KDB),y,m)	+= patch.o measure.o
+endif
Index: linux/arch/ia64/test-module/cmc.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ linux/arch/ia64/test-module/cmc.c	2008-10-27 18:29:21.392697005 -0700
@@ -0,0 +1,47 @@
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/vmalloc.h>
+#include <asm/sal.h>
+
+MODULE_LICENSE("GPL");
+
+static int __init
+cmc_init(void)
+{
+	int i, count = 0;
+	unsigned char *log_buffer;
+	struct ia64_sal_retval isrv;
+	printk(KERN_ERR "%s: starting\n", __FUNCTION__);
+
+	i = ia64_sal_get_state_info_size(SAL_INFO_TYPE_CMC);
+	if (!i) {
+		printk(KERN_ERR "%s: no size for SAL_INFO_TYPE_CMC records\n", __FUNCTION__);
+		return -1;
+	}
+	log_buffer = vmalloc(i);
+	if (!log_buffer) {
+		printk(KERN_ERR "%s: cannot vmalloc %d bytes for SAL_INFO_TYPE_CMC records\n", __FUNCTION__, i);
+		return -1;
+	}
+	for (i = 0; i < 1000; ++i) {
+		SAL_CALL(isrv, SAL_GET_STATE_INFO, SAL_INFO_TYPE_CMC, 0, (u64 *)log_buffer, 0, 0, 0, 0);
+		if (isrv.status == -5)
+			break;	/* no more records */
+		if (isrv.status) {
+			printk(KERN_ERR "%s: SAL_GET_STATE_INFO failed %ld\n", __FUNCTION__, isrv.status);
+			break;
+		}
+		SAL_CALL(isrv, SAL_CLEAR_STATE_INFO, SAL_INFO_TYPE_CMC, 0, 0, 0, 0, 0, 0);
+		if (isrv.status < 0 || (isrv.status && isrv.status != 3)) {
+			printk(KERN_ERR "%s: SAL_CLEAR_STATE_INFO failed %ld\n", __FUNCTION__, isrv.status);
+			break;
+		}
+		++count;
+	}
+
+	vfree(log_buffer);
+	printk(KERN_ERR "%s: %d SAL_INFO_TYPE_CMC records cleared\n", __FUNCTION__, count);
+	return 0;
+}
+
+module_init(cmc_init)
Index: linux/arch/ia64/test-module/debug.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ linux/arch/ia64/test-module/debug.c	2008-10-27 18:29:21.416696507 -0700
@@ -0,0 +1,89 @@
+#include <linux/slab.h>
+#include <linux/kdb.h>
+#include <linux/module.h>
+
+MODULE_LICENSE("GPL");
+
+int victim;
+static int trap29count;
+
+extern int (*trap29)(unsigned long ifa, struct pt_regs *regs);
+extern int (*trap36)(unsigned long ifa, struct pt_regs *regs);
+
+static int do_trap29(unsigned long ifa, struct pt_regs *regs)
+{
+	if (user_mode(regs))
+		return 0;
+	kdb_printf("trap 29 ifa=0x%016lx iip=0x%016lx count=%d victim=%d\n", ifa, regs->cr_iip, trap29count, victim);
+#if 0
+	ia64_psr(regs)->db = 0;
+	ia64_psr(regs)->ss = 1;
+#else
+	if (trap29count >= 3) {
+		kdb_printf("db is looping, disabling it\n");
+		ia64_psr(regs)->db = 0;
+	} else {
+		++trap29count;
+		ia64_psr(regs)->dd = 1;
+	}
+#endif
+	return 1;
+}
+
+static int do_trap36(unsigned long ifa, struct pt_regs *regs)
+{
+	if (user_mode(regs))
+		return 0;
+	kdb_printf("trap 36 iip=0x%016lx victim=%d\n", regs->cr_iip, victim);
+	ia64_psr(regs)->db = 1;
+	ia64_psr(regs)->ss = 0;
+	return 1;
+}
+
+static void setdbr(unsigned long regnum, unsigned long address, unsigned long mask)
+{
+	kdb_printf("dbr[%ld]=0x%016lx dbr[%ld]=0x%016lx\n", regnum, address, regnum+1, mask);
+	__asm__ __volatile__ ("mov dbr[%0]=%1;;mov dbr[%2]=%3;;"::"r"(regnum),"r"(address),"r"(regnum+1),"r"(mask));
+	ia64_srlz_d();
+}
+
+static void setpsrdb(int on)
+{
+	unsigned long tmp;
+	kdb_printf("%s: on=%d\n", __FUNCTION__, on);
+	if (on)
+		__asm__ __volatile__ ("mov %0=psr;;dep %0=-1,%0,24,1;;mov psr.l=%0;;srlz.d;;srlz.i;;":"=r"(tmp)::"memory");
+	else
+		__asm__ __volatile__ ("mov %0=psr;;dep %0=0,%0,24,1;;mov psr.l=%0;;srlz.d;;srlz.i;;":"=r"(tmp)::"memory");
+}
+
+static void set_victim(void)
+{
+	victim = 1;
+}
+
+static int __init init_debug(void)
+{
+	kdb_printf("%s: start\n", __FUNCTION__);
+	trap29 = &do_trap29;
+	trap36 = &do_trap36;
+	setdbr(0, (unsigned long)&victim, 1UL<<62 | 1UL<<56 | (-4UL & 0xffffffffffffffUL));
+	setpsrdb(1);
+	kdb_printf("%s: test\n", __FUNCTION__);
+	set_victim();
+	setpsrdb(0);
+	kdb_printf("%s: end\n", __FUNCTION__);
+	return 0;
+}
+
+static void __exit exit_debug(void)
+{
+	kdb_printf("%s: start\n", __FUNCTION__);
+	trap29 = NULL;
+	trap36 = NULL;
+	setdbr(0, 0, 0);
+	kdb_printf("%s: end\n", __FUNCTION__);
+}
+
+module_init(init_debug)
+module_exit(exit_debug)
Index: linux/arch/ia64/test-module/do_dump.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ linux/arch/ia64/test-module/do_dump.c	2008-10-27 18:29:21.440696008 -0700
@@ -0,0 +1,14 @@
+#include <linux/dump.h>
+#include <linux/module.h>
+
+MODULE_LICENSE("GPL");
+
+static int __init init_do_dump(void)
+{
+	printk(KERN_ERR "do_dump start\n");
+	dump("do_dump", NULL);
+	printk(KERN_ERR "do_dump end\n");
+	return 0;
+}
+
+module_init(init_do_dump)
Index: linux/arch/ia64/test-module/do_hang.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ linux/arch/ia64/test-module/do_hang.c	2008-10-27 18:29:21.464695510 -0700
@@ -0,0 +1,26 @@
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/smp_lock.h>
+
+MODULE_LICENSE("GPL");
+
+unsigned long do_hang;
+module_param(do_hang, ulong, 0664);
+
+static int __init
+do_hang_start(void)
+{
+	lock_kernel();
+	for (;;)
+		cpu_relax();
+	return 0;
+}
+
+static void do_hang_stop(void)
+{
+	printk(KERN_INFO "do_hang module exiting.\n");
+}
+
+module_init(do_hang_start)
+module_exit(do_hang_stop)
Index: linux/arch/ia64/test-module/do_mca.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ linux/arch/ia64/test-module/do_mca.c	2008-10-27 18:29:21.488695012 -0700
@@ -0,0 +1,21 @@
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <asm/uaccess.h>
+
+MODULE_LICENSE("GPL");
+
+unsigned long do_mca;
+module_param(do_mca, ulong, 0664);
+
+static int __init
+do_mca_init(void)
+{
+	// char buf[1024];
+	// printk(KERN_ERR "%s: starting\n", __FUNCTION__);
+	// __copy_to_user(buf, (void *)do_mca, sizeof(buf));
+	char c = *(char *)do_mca;
+	printk("%s: %c\n", __FUNCTION__, c);
+	return 0;
+}
+
+module_init(do_mca_init)
Index: linux/arch/ia64/test-module/do_panic.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ linux/arch/ia64/test-module/do_panic.c	2008-10-27 18:29:21.512694514 -0700
@@ -0,0 +1,17 @@
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <asm/uaccess.h>
+
+MODULE_LICENSE("GPL");
+
+unsigned long do_panic;
+module_param(do_panic, ulong, 0664);
+
+static int __init
+do_panic_init(void)
+{
+	panic("panic from test-module\n");
+	return 0;
+}
+
+module_init(do_panic_init)
Index: linux/arch/ia64/test-module/do_spin.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ linux/arch/ia64/test-module/do_spin.c	2008-10-27 18:29:21.532694099 -0700
@@ -0,0 +1,34 @@
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/cpumask.h>
+#ifdef	CONFIG_KDB
+#include <linux/kdb.h>
+#else
+#define	kdb_printf printk
+#endif
+
+MODULE_AUTHOR("SGI");
+MODULE_DESCRIPTION("Spin disabled");
+MODULE_LICENSE("GPL");
+
+int kdb_spin = 1;
+
+static int __init
+do_spin_init(void)
+{
+	set_cpus_allowed(current, cpumask_of_cpu(num_online_cpus() > 4 ? 4 : num_online_cpus() > 2 ? 2 : num_online_cpus() > 1 ? 1 : 0));
+	local_irq_disable();
+	kdb_printf("%s: on cpu %d\n", __FUNCTION__, smp_processor_id());
+	while (kdb_spin)
+		cpu_relax();
+	local_irq_enable();
+	return 0;
+}
+
+static void __exit
+do_spin_exit(void)
+{
+}
+
+module_init(do_spin_init)
+module_exit(do_spin_exit)
Index: linux/arch/ia64/test-module/kdb_enter.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ linux/arch/ia64/test-module/kdb_enter.c	2008-10-27 18:29:21.564693435 -0700
@@ -0,0 +1,26 @@
+#include <linux/module.h>
+#include <linux/kdb.h>
+
+MODULE_LICENSE("GPL");
+
+static int __init
+kdb_enter_init(void)
+{
+	int cpu;
+	for_each_online_cpu(cpu) {
+		cpumask_t save_cpus_allowed = current->cpus_allowed;
+		cpumask_t new_cpus_allowed = cpumask_of_cpu(cpu);
+		set_cpus_allowed(current, new_cpus_allowed);
+		asm("\tint $129\n");
+		set_cpus_allowed(current, save_cpus_allowed);
+	}
+	return 0;
+}
+
+static void __exit
+kdb_enter_exit(void)
+{
+}
+
+module_init(kdb_enter_init)
+module_exit(kdb_enter_exit)
Index: linux/arch/ia64/test-module/measure.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ linux/arch/ia64/test-module/measure.c	2008-10-27 18:29:21.608692522 -0700
@@ -0,0 +1,77 @@
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/preempt.h>
+#include <asm/kregs.h>
+#include <asm/timex.h>
+
+MODULE_LICENSE("GPL");
+
+#define LOOPS 1000000
+
+static int __init init_measure(void)
+{
+	int loop;
+	register int cpu;
+	unsigned long start, end, empty_loop, cpu_loop, k3_loop;
+	printk("%s: start\n", __FUNCTION__);
+	preempt_disable();
+
+	local_irq_disable();
+	start = get_cycles();
+	barrier();
+	for (loop = 0; loop < LOOPS; ++loop) {
+		/* ensure that all loops are the same size (2 bundles) */
+		asm volatile ("nop 0; nop 0; nop 0;");
+		barrier();
+	};
+	end = get_cycles();
+	barrier();
+	local_irq_enable();
+	empty_loop = end - start;
+
+	local_irq_disable();
+	start = get_cycles();
+	barrier();
+	for (loop = 0; loop < LOOPS; ++loop) {
+		/* hand code the read of smp_processor_id() to stop gcc moving
+		 * the address calculation outside the loop
+		 */
+		asm volatile ("adds r14=%0,r13"
+			      ";;"
+			      "ld4 r15=[r14]"
+			      : :
+			      "i" (IA64_TASK_SIZE + offsetof(struct thread_info, cpu)) :
+			      "r14", "r15" );
+		barrier();
+	};
+	end = get_cycles();
+	barrier();
+	local_irq_enable();
+	cpu_loop = end - start;
+
+	local_irq_disable();
+	start = get_cycles();
+	barrier();
+	for (loop = 0; loop < LOOPS; ++loop) {
+		cpu = ia64_get_kr(IA64_KR_PER_CPU_DATA);
+		barrier();
+	};
+	end = get_cycles();
+	barrier();
+	local_irq_enable();
+	k3_loop = end - start;
+
+	preempt_enable();
+	printk("%s: empty_loop %ld cpu_loop %ld k3_loop %ld\n", __FUNCTION__, empty_loop, cpu_loop, k3_loop);
+	return 0;
+}
+
+static void __exit exit_measure(void)
+{
+	printk("%s: start\n", __FUNCTION__);
+	printk("%s: end\n", __FUNCTION__);
+}
+
+module_init(init_measure)
+module_exit(exit_measure)
Index: linux/arch/ia64/test-module/patch.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ linux/arch/ia64/test-module/patch.c	2008-10-27 18:29:21.628692107 -0700
@@ -0,0 +1,103 @@
+#include <linux/kdb.h>
+#include <linux/module.h>
+
+MODULE_LICENSE("GPL");
+
+static void
+ia64_patch (u64 insn_addr, u64 mask, u64 val)
+{
+	u64 m0, m1, v0, v1, b0, b1, *b = (u64 *) (insn_addr & -16);
+#	define insn_mask ((1UL << 41) - 1)
+	unsigned long shift;
+
+	b0 = b[0]; b1 = b[1];
+	shift = 5 + 41 * (insn_addr % 16); /* 5 bits of template, then 3 x 41-bit instructions */
+	if (shift >= 64) {
+		m1 = mask << (shift - 64);
+		v1 = val << (shift - 64);
+	} else {
+		m0 = mask << shift; m1 = mask >> (64 - shift);
+		v0 = val  << shift; v1 = val >> (64 - shift);
+		b[0] = (b0 & ~m0) | (v0 & m0);
+	}
+	b[1] = (b1 & ~m1) | (v1 & m1);
+}
+
+static void
+ia64_patch_imm64 (u64 insn_addr, u64 val)
+{
+	/* The assembler may generate offset pointing to either slot 1
+	   or slot 2 for a long (2-slot) instruction, occupying slots 1
+	   and 2.  */
+  	insn_addr &= -16UL;
+	ia64_patch(insn_addr + 2,
+		   0x01fffefe000UL, (  ((val & 0x8000000000000000UL) >> 27) /* bit 63 -> 36 */
+				     | ((val & 0x0000000000200000UL) <<  0) /* bit 21 -> 21 */
+				     | ((val & 0x00000000001f0000UL) <<  6) /* bit 16 -> 22 */
+				     | ((val & 0x000000000000ff80UL) << 20) /* bit  7 -> 27 */
+				     | ((val & 0x000000000000007fUL) << 13) /* bit  0 -> 13 */));
+	ia64_patch(insn_addr + 1, 0x1ffffffffffUL, val >> 22);
+}
+
+static void
+ia64_patch_imm60 (u64 insn_addr, u64 val)
+{
+	/* The assembler may generate offset pointing to either slot 1
+	   or slot 2 for a long (2-slot) instruction, occupying slots 1
+	   and 2.  */
+  	insn_addr &= -16UL;
+	ia64_patch(insn_addr + 2,
+		   0x011ffffe000UL, (  ((val & 0x0800000000000000UL) >> 23) /* bit 59 -> 36 */
+				     | ((val & 0x00000000000fffffUL) << 13) /* bit  0 -> 13 */));
+	ia64_patch(insn_addr + 1, 0x1fffffffffcUL, val >> 18);
+}
+
+struct plt_entry {
+	unsigned char bundle[3][16];
+};
+static struct plt_entry ia64_plt_mask;
+
+static int __init init_patch(void)
+{
+	int i, j;
+	kdb_printf("%s: 2 bundle\n", __FUNCTION__);
+	for (i = 0; i < 2; ++i)
+		for (j = 0; j < 16; ++j)
+			ia64_plt_mask.bundle[i][j] = 0xff;
+	ia64_patch_imm64((u64) (ia64_plt_mask.bundle + 0), 0);
+	ia64_patch_imm60((u64) (ia64_plt_mask.bundle + 1), 0);
+	for (i = 0; i < 2; ++i) {
+		for (j = 0; j < 16; ++j) {
+			kdb_printf("0x%02x", ia64_plt_mask.bundle[i][j]);
+			if (j != 15)
+				kdb_printf(", ");
+			if (j % 6 == 5 || j == 15)
+				kdb_printf("\n");
+		}
+	}
+	kdb_printf("\n%s: 3 bundle\n", __FUNCTION__);
+	for (i = 0; i < 3; ++i)
+		for (j = 0; j < 16; ++j)
+			ia64_plt_mask.bundle[i][j] = 0xff;
+	ia64_patch_imm64((u64) (ia64_plt_mask.bundle + 0), 0);
+	ia64_patch_imm64((u64) (ia64_plt_mask.bundle + 1), 0);
+	for (i = 0; i < 3; ++i) {
+		for (j = 0; j < 16; ++j) {
+			kdb_printf("0x%02x", ia64_plt_mask.bundle[i][j]);
+			if (j != 15)
+				kdb_printf(", ");
+			if (j % 6 == 5 || j == 15)
+				kdb_printf("\n");
+		}
+	}
+	return 0;
+}
+
+static void __exit exit_patch(void)
+{
+	kdb_printf("%s: start\n", __FUNCTION__);
+	kdb_printf("%s: end\n", __FUNCTION__);
+}
+
+module_init(init_patch)
+module_exit(exit_patch)
Index: linux/arch/ia64/test-module/spin.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ linux/arch/ia64/test-module/spin.c	2008-10-27 18:29:21.652691608 -0700
@@ -0,0 +1,57 @@
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/spinlock.h>
+#include <linux/kdb.h>
+
+MODULE_LICENSE("GPL");
+
+static spinlock_t spintest = SPIN_LOCK_UNLOCKED;
+// extern spinlock_t swaplock;
+static int do_printf = 1;
+static int do_leaf = 0;
+module_param(do_printf, int, 0664);
+module_param(do_leaf, int, 0664);
+
+void spin_init4(int k, int l, int m)
+{
+	spin_lock(&spintest);
+	spin_lock(&spintest);
+}
+
+void spin_init3(int k, int l)
+{
+	int i;
+	if (do_printf)
+		kdb_printf("%s\n", __FUNCTION__);
+	spin_lock(&spintest);
+	i = *(int *)&spintest;
+	if (do_printf)
+		kdb_printf("%s %d\n", __FUNCTION__, i);
+	spin_lock(&spintest);
+	if (do_printf)
+		kdb_printf("%s\n", __FUNCTION__);
+}
+
+void spin_init2(void)
+{
+	if (do_printf)
+		kdb_printf("%s\n", __FUNCTION__);
+	if (do_leaf)
+		spin_init4(15, 30, 45);
+	else
+		spin_init3(15, 30);
+	if (do_printf)
+		kdb_printf("%s\n", __FUNCTION__);
+}
+
+static int __init
+spin_init(void)
+{
+	if (do_printf)
+		kdb_printf("%s\n", __FUNCTION__);
+	// spin_lock(&swaplock);
+	spin_init2();
+	return 0;
+}
+
+module_init(spin_init)
Index: linux/arch/x86/test-module/cmc.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ linux/arch/x86/test-module/cmc.c	2008-10-27 18:29:21.680691027 -0700
@@ -0,0 +1,47 @@
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/vmalloc.h>
+#include <asm/sal.h>
+
+MODULE_LICENSE("GPL");
+
+static int __init
+cmc_init(void)
+{
+	int i, count = 0;
+	unsigned char *log_buffer;
+	struct ia64_sal_retval isrv;
+	printk(KERN_ERR "%s: starting\n", __FUNCTION__);
+
+	i = ia64_sal_get_state_info_size(SAL_INFO_TYPE_CMC);
+	if (!i) {
+		printk(KERN_ERR "%s: no size for SAL_INFO_TYPE_CMC records\n", __FUNCTION__);
+		return -1;
+	}
+	log_buffer = vmalloc(i);
+	if (!log_buffer) {
+		printk(KERN_ERR "%s: cannot vmalloc %d bytes for SAL_INFO_TYPE_CMC records\n", __FUNCTION__, i);
+		return -1;
+	}
+	for (i = 0; i < 1000; ++i) {
+		SAL_CALL(isrv, SAL_GET_STATE_INFO, SAL_INFO_TYPE_CMC, 0, (u64 *)log_buffer, 0, 0, 0, 0);
+		if (isrv.status == -5)
+			break;	/* no more records */
+		if (isrv.status) {
+			printk(KERN_ERR "%s: SAL_GET_STATE_INFO failed %ld\n", __FUNCTION__, isrv.status);
+			break;
+		}
+		SAL_CALL(isrv, SAL_CLEAR_STATE_INFO, SAL_INFO_TYPE_CMC, 0, 0, 0, 0, 0, 0);
+		if (isrv.status < 0 || (isrv.status && isrv.status != 3)) {
+			printk(KERN_ERR "%s: SAL_CLEAR_STATE_INFO failed %ld\n", __FUNCTION__, isrv.status);
+			break;
+		}
+		++count;
+	}
+
+	vfree(log_buffer);
+	printk(KERN_ERR "%s: %d SAL_INFO_TYPE_CMC records cleared\n", __FUNCTION__, count);
+	return 0;
+}
+
+module_init(cmc_init)
Index: linux/arch/x86/test-module/debug.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ linux/arch/x86/test-module/debug.c	2008-10-27 18:29:21.704690529 -0700
@@ -0,0 +1,89 @@
+#include <linux/slab.h>
+#include <linux/kdb.h>
+#include <linux/module.h>
+
+MODULE_LICENSE("GPL");
+
+int victim;
+static int trap29count;
+
+extern int (*trap29)(unsigned long ifa, struct pt_regs *regs);
+extern int (*trap36)(unsigned long ifa, struct pt_regs *regs);
+
+static int do_trap29(unsigned long ifa, struct pt_regs *regs)
+{
+	if (user_mode(regs))
+		return 0;
+	kdb_printf("trap 29 ifa=0x%016lx iip=0x%016lx count=%d victim=%d\n", ifa, regs->cr_iip, trap29count, victim);
+#if 0
+	ia64_psr(regs)->db = 0;
+	ia64_psr(regs)->ss = 1;
+#else
+	if (trap29count >= 3) {
+		kdb_printf("db is looping, disabling it\n");
+		ia64_psr(regs)->db = 0;
+	} else {
+		++trap29count;
+		ia64_psr(regs)->dd = 1;
+	}
+#endif
+	return 1;
+}
+
+static int do_trap36(unsigned long ifa, struct pt_regs *regs)
+{
+	if (user_mode(regs))
+		return 0;
+	kdb_printf("trap 36 iip=0x%016lx victim=%d\n", regs->cr_iip, victim);
+	ia64_psr(regs)->db = 1;
+	ia64_psr(regs)->ss = 0;
+	return 1;
+}
+
+static void setdbr(unsigned long regnum, unsigned long address, unsigned long mask)
+{
+	kdb_printf("dbr[%ld]=0x%016lx dbr[%ld]=0x%016lx\n", regnum, address, regnum+1, mask);
+	__asm__ __volatile__ ("mov dbr[%0]=%1;;mov dbr[%2]=%3;;"::"r"(regnum),"r"(address),"r"(regnum+1),"r"(mask));
+	ia64_srlz_d();
+}
+
+static void setpsrdb(int on)
+{
+	unsigned long tmp;
+	kdb_printf("%s: on=%d\n", __FUNCTION__, on);
+	if (on)
+		__asm__ __volatile__ ("mov %0=psr;;dep %0=-1,%0,24,1;;mov psr.l=%0;;srlz.d;;srlz.i;;":"=r"(tmp)::"memory");
+	else
+		__asm__ __volatile__ ("mov %0=psr;;dep %0=0,%0,24,1;;mov psr.l=%0;;srlz.d;;srlz.i;;":"=r"(tmp)::"memory");
+}
+
+static void set_victim(void)
+{
+	victim = 1;
+}
+
+static int __init init_debug(void)
+{
+	kdb_printf("%s: start\n", __FUNCTION__);
+	trap29 = &do_trap29;
+	trap36 = &do_trap36;
+	setdbr(0, (unsigned long)&victim, 1UL<<62 | 1UL<<56 | (-4UL & 0xffffffffffffffUL));
+	setpsrdb(1);
+	kdb_printf("%s: test\n", __FUNCTION__);
+	set_victim();
+	setpsrdb(0);
+	kdb_printf("%s: end\n", __FUNCTION__);
+	return 0;
+}
+
+static void __exit exit_debug(void)
+{
+	kdb_printf("%s: start\n", __FUNCTION__);
+	trap29 = NULL;
+	trap36 = NULL;
+	setdbr(0, 0, 0);
+	kdb_printf("%s: end\n", __FUNCTION__);
+}
+
+module_init(init_debug)
+module_exit(exit_debug)
Index: linux/arch/x86/test-module/do_dump.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ linux/arch/x86/test-module/do_dump.c	2008-10-27 18:29:21.724690114 -0700
@@ -0,0 +1,14 @@
+#include <linux/dump.h>
+#include <linux/module.h>
+
+MODULE_LICENSE("GPL");
+
+static int __init init_do_dump(void)
+{
+	printk(KERN_ERR "do_dump start\n");
+	dump("do_dump", NULL);
+	printk(KERN_ERR "do_dump end\n");
+	return 0;
+}
+
+module_init(init_do_dump)
Index: linux/arch/x86/test-module/do_hang.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ linux/arch/x86/test-module/do_hang.c	2008-10-27 18:29:21.748689616 -0700
@@ -0,0 +1,26 @@
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/smp_lock.h>
+
+MODULE_LICENSE("GPL");
+
+unsigned long do_hang;
+module_param(do_hang, ulong, 0664);
+
+static int __init
+do_hang_start(void)
+{
+	lock_kernel();
+	for (;;)
+		cpu_relax();
+	return 0;
+}
+
+static void do_hang_stop(void)
+{
+	printk(KERN_INFO "do_hang module exiting.\n");
+}
+
+module_init(do_hang_start)
+module_exit(do_hang_stop)
Index: linux/arch/x86/test-module/do_mca.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ linux/arch/x86/test-module/do_mca.c	2008-10-27 18:29:21.772689118 -0700
@@ -0,0 +1,21 @@
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <asm/uaccess.h>
+
+MODULE_LICENSE("GPL");
+
+unsigned long do_mca;
+module_param(do_mca, ulong, 0664);
+
+static int __init
+do_mca_init(void)
+{
+	// char buf[1024];
+	// printk(KERN_ERR "%s: starting\n", __FUNCTION__);
+	// __copy_to_user(buf, (void *)do_mca, sizeof(buf));
+	char c = *(char *)do_mca;
+	printk("%s: %c\n", __FUNCTION__, c);
+	return 0;
+}
+
+module_init(do_mca_init)
Index: linux/arch/x86/test-module/do_panic.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ linux/arch/x86/test-module/do_panic.c	2008-10-27 18:29:21.800688537 -0700
@@ -0,0 +1,17 @@
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <asm/uaccess.h>
+
+MODULE_LICENSE("GPL");
+
+unsigned long do_panic;
+module_param(do_panic, ulong, 0664);
+
+static int __init
+do_panic_init(void)
+{
+	panic("panic from test-module\n");
+	return 0;
+}
+
+module_init(do_panic_init)
Index: linux/arch/x86/test-module/do_spin.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ linux/arch/x86/test-module/do_spin.c	2008-10-27 18:29:21.828687956 -0700
@@ -0,0 +1,34 @@
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/cpumask.h>
+#ifdef	CONFIG_KDB
+#include <linux/kdb.h>
+#else
+#define	kdb_printf printk
+#endif
+
+MODULE_AUTHOR("SGI");
+MODULE_DESCRIPTION("Spin disabled");
+MODULE_LICENSE("GPL");
+
+int kdb_spin = 1;
+
+static int __init
+do_spin_init(void)
+{
+	set_cpus_allowed(current, cpumask_of_cpu(num_online_cpus() > 4 ? 4 : num_online_cpus() > 2 ? 2 : num_online_cpus() > 1 ? 1 : 0));
+	local_irq_disable();
+	kdb_printf("%s: on cpu %d\n", __FUNCTION__, smp_processor_id());
+	while (kdb_spin)
+		cpu_relax();
+	local_irq_enable();
+	return 0;
+}
+
+static void __exit
+do_spin_exit(void)
+{
+}
+
+module_init(do_spin_init)
+module_exit(do_spin_exit)
Index: linux/arch/x86/test-module/kdb_enter.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ linux/arch/x86/test-module/kdb_enter.c	2008-10-27 18:29:21.856687375 -0700
@@ -0,0 +1,26 @@
+#include <linux/module.h>
+#include <linux/kdb.h>
+
+MODULE_LICENSE("GPL");
+
+static int __init
+kdb_enter_init(void)
+{
+	int cpu;
+	for_each_online_cpu(cpu) {
+		cpumask_t save_cpus_allowed = current->cpus_allowed;
+		cpumask_t new_cpus_allowed = cpumask_of_cpu(cpu);
+		set_cpus_allowed(current, new_cpus_allowed);
+		asm("\tint $129\n");
+		set_cpus_allowed(current, save_cpus_allowed);
+	}
+	return 0;
+}
+
+static void __exit
+kdb_enter_exit(void)
+{
+}
+
+module_init(kdb_enter_init)
+module_exit(kdb_enter_exit)
Index: linux/arch/x86/test-module/measure.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ linux/arch/x86/test-module/measure.c	2008-10-27 18:29:21.876686959 -0700
@@ -0,0 +1,77 @@
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/preempt.h>
+#include <asm/kregs.h>
+#include <asm/timex.h>
+
+MODULE_LICENSE("GPL");
+
+#define LOOPS 1000000
+
+static int __init init_measure(void)
+{
+	int loop;
+	register int cpu;
+	unsigned long start, end, empty_loop, cpu_loop, k3_loop;
+	printk("%s: start\n", __FUNCTION__);
+	preempt_disable();
+
+	local_irq_disable();
+	start = get_cycles();
+	barrier();
+	for (loop = 0; loop < LOOPS; ++loop) {
+		/* ensure that all loops are the same size (2 bundles) */
+		asm volatile ("nop 0; nop 0; nop 0;");
+		barrier();
+	};
+	end = get_cycles();
+	barrier();
+	local_irq_enable();
+	empty_loop = end - start;
+
+	local_irq_disable();
+	start = get_cycles();
+	barrier();
+	for (loop = 0; loop < LOOPS; ++loop) {
+		/* hand code the read of smp_processor_id() to stop gcc moving
+		 * the address calculation outside the loop
+		 */
+		asm volatile ("adds r14=%0,r13"
+			      ";;"
+			      "ld4 r15=[r14]"
+			      : :
+			      "i" (IA64_TASK_SIZE + offsetof(struct thread_info, cpu)) :
+			      "r14", "r15" );
+		barrier();
+	};
+	end = get_cycles();
+	barrier();
+	local_irq_enable();
+	cpu_loop = end - start;
+
+	local_irq_disable();
+	start = get_cycles();
+	barrier();
+	for (loop = 0; loop < LOOPS; ++loop) {
+		cpu = ia64_get_kr(IA64_KR_PER_CPU_DATA);
+		barrier();
+	};
+	end = get_cycles();
+	barrier();
+	local_irq_enable();
+	k3_loop = end - start;
+
+	preempt_enable();
+	printk("%s: empty_loop %ld cpu_loop %ld k3_loop %ld\n", __FUNCTION__, empty_loop, cpu_loop, k3_loop);
+	return 0;
+}
+
+static void __exit exit_measure(void)
+{
+	printk("%s: start\n", __FUNCTION__);
+	printk("%s: end\n", __FUNCTION__);
+}
+
+module_init(init_measure)
+module_exit(exit_measure)
Index: linux/arch/x86/test-module/patch.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ linux/arch/x86/test-module/patch.c	2008-10-27 18:29:21.900686461 -0700
@@ -0,0 +1,103 @@
+#include <linux/kdb.h>
+#include <linux/module.h>
+
+MODULE_LICENSE("GPL");
+
+static void
+ia64_patch (u64 insn_addr, u64 mask, u64 val)
+{
+	u64 m0, m1, v0, v1, b0, b1, *b = (u64 *) (insn_addr & -16);
+#	define insn_mask ((1UL << 41) - 1)
+	unsigned long shift;
+
+	b0 = b[0]; b1 = b[1];
+	shift = 5 + 41 * (insn_addr % 16); /* 5 bits of template, then 3 x 41-bit instructions */
+	if (shift >= 64) {
+		m1 = mask << (shift - 64);
+		v1 = val << (shift - 64);
+	} else {
+		m0 = mask << shift; m1 = mask >> (64 - shift);
+		v0 = val  << shift; v1 = val >> (64 - shift);
+		b[0] = (b0 & ~m0) | (v0 & m0);
+	}
+	b[1] = (b1 & ~m1) | (v1 & m1);
+}
+
+static void
+ia64_patch_imm64 (u64 insn_addr, u64 val)
+{
+	/* The assembler may generate offset pointing to either slot 1
+	   or slot 2 for a long (2-slot) instruction, occupying slots 1
+	   and 2.  */
+  	insn_addr &= -16UL;
+	ia64_patch(insn_addr + 2,
+		   0x01fffefe000UL, (  ((val & 0x8000000000000000UL) >> 27) /* bit 63 -> 36 */
+				     | ((val & 0x0000000000200000UL) <<  0) /* bit 21 -> 21 */
+				     | ((val & 0x00000000001f0000UL) <<  6) /* bit 16 -> 22 */
+				     | ((val & 0x000000000000ff80UL) << 20) /* bit  7 -> 27 */
+				     | ((val & 0x000000000000007fUL) << 13) /* bit  0 -> 13 */));
+	ia64_patch(insn_addr + 1, 0x1ffffffffffUL, val >> 22);
+}
+
+static void
+ia64_patch_imm60 (u64 insn_addr, u64 val)
+{
+	/* The assembler may generate offset pointing to either slot 1
+	   or slot 2 for a long (2-slot) instruction, occupying slots 1
+	   and 2.  */
+  	insn_addr &= -16UL;
+	ia64_patch(insn_addr + 2,
+		   0x011ffffe000UL, (  ((val & 0x0800000000000000UL) >> 23) /* bit 59 -> 36 */
+				     | ((val & 0x00000000000fffffUL) << 13) /* bit  0 -> 13 */));
+	ia64_patch(insn_addr + 1, 0x1fffffffffcUL, val >> 18);
+}
+
+struct plt_entry {
+	unsigned char bundle[3][16];
+};
+static struct plt_entry ia64_plt_mask;
+
+static int __init init_patch(void)
+{
+	int i, j;
+	kdb_printf("%s: 2 bundle\n", __FUNCTION__);
+	for (i = 0; i < 2; ++i)
+		for (j = 0; j < 16; ++j)
+			ia64_plt_mask.bundle[i][j] = 0xff;
+	ia64_patch_imm64((u64) (ia64_plt_mask.bundle + 0), 0);
+	ia64_patch_imm60((u64) (ia64_plt_mask.bundle + 1), 0);
+	for (i = 0; i < 2; ++i) {
+		for (j = 0; j < 16; ++j) {
+			kdb_printf("0x%02x", ia64_plt_mask.bundle[i][j]);
+			if (j != 15)
+				kdb_printf(", ");
+			if (j % 6 == 5 || j == 15)
+				kdb_printf("\n");
+		}
+	}
+	kdb_printf("\n%s: 3 bundle\n", __FUNCTION__);
+	for (i = 0; i < 3; ++i)
+		for (j = 0; j < 16; ++j)
+			ia64_plt_mask.bundle[i][j] = 0xff;
+	ia64_patch_imm64((u64) (ia64_plt_mask.bundle + 0), 0);
+	ia64_patch_imm64((u64) (ia64_plt_mask.bundle + 1), 0);
+	for (i = 0; i < 3; ++i) {
+		for (j = 0; j < 16; ++j) {
+			kdb_printf("0x%02x", ia64_plt_mask.bundle[i][j]);
+			if (j != 15)
+				kdb_printf(", ");
+			if (j % 6 == 5 || j == 15)
+				kdb_printf("\n");
+		}
+	}
+	return 0;
+}
+
+static void __exit exit_patch(void)
+{
+	kdb_printf("%s: start\n", __FUNCTION__);
+	kdb_printf("%s: end\n", __FUNCTION__);
+}
+
+module_init(init_patch)
+module_exit(exit_patch)
Index: linux/arch/x86/test-module/spin.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ linux/arch/x86/test-module/spin.c	2008-10-27 18:29:21.928685880 -0700
@@ -0,0 +1,57 @@
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/spinlock.h>
+#include <linux/kdb.h>
+
+MODULE_LICENSE("GPL");
+
+static spinlock_t spintest = SPIN_LOCK_UNLOCKED;
+// extern spinlock_t swaplock;
+static int do_printf = 1;
+static int do_leaf = 0;
+module_param(do_printf, int, 0664);
+module_param(do_leaf, int, 0664);
+
+void spin_init4(int k, int l, int m)
+{
+	spin_lock(&spintest);
+	spin_lock(&spintest);
+}
+
+void spin_init3(int k, int l)
+{
+	int i;
+	if (do_printf)
+		kdb_printf("%s\n", __FUNCTION__);
+	spin_lock(&spintest);
+	i = *(int *)&spintest;
+	if (do_printf)
+		kdb_printf("%s %d\n", __FUNCTION__, i);
+	spin_lock(&spintest);
+	if (do_printf)
+		kdb_printf("%s\n", __FUNCTION__);
+}
+
+void spin_init2(void)
+{
+	if (do_printf)
+		kdb_printf("%s\n", __FUNCTION__);
+	if (do_leaf)
+		spin_init4(15, 30, 45);
+	else
+		spin_init3(15, 30);
+	if (do_printf)
+		kdb_printf("%s\n", __FUNCTION__);
+}
+
+static int __init
+spin_init(void)
+{
+	if (do_printf)
+		kdb_printf("%s\n", __FUNCTION__);
+	// spin_lock(&swaplock);
+	spin_init2();
+	return 0;
+}
+
+module_init(spin_init)
Index: linux/arch/x86/test-module/Makefile
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ linux/arch/x86/test-module/Makefile	2008-10-27 18:29:21.948685465 -0700
@@ -0,0 +1,7 @@
+obj-$(subst $(CONFIG_KDB),y,m)	+= do_mca.o spin.o
+obj-$(subst $(CONFIG_DUMP),y,m) += do_dump.o
+obj-m				+= do_mca.o do_spin.o kdb_enter.o do_panic.o \
+				   do_hang.o
+ifdef CONFIG_IA64
+obj-$(subst $(CONFIG_KDB),y,m)	+= debug.o cmc.o patch.o measure.o
+endif
Index: linux/arch/x86/Makefile
===================================================================
--- linux.orig/arch/x86/Makefile	2008-10-27 17:00:15.847881864 -0700
+++ linux/arch/x86/Makefile	2008-10-27 18:29:21.968685050 -0700
@@ -172,7 +172,8 @@ drivers-$(CONFIG_FB) += arch/x86/video/
 endif
 
 # KDB support
-drivers-$(CONFIG_KDB) += arch/x86/kdb/
+drivers-$(CONFIG_KDB) += arch/x86/kdb/ \
+			 arch/x86/test-module/
 
 ####
 # boot loader support. Several targets are kept for legacy purposes
