lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date:	Wed, 11 May 2011 16:13:56 -0400
From:	Mark Salter <msalter@...hat.com>
To:	linux-kernel@...r.kernel.org
Subject: [PATCH 09/16] C6X: add kernel files

Signed-off-by: Mark Salter <msalter@...hat.com>
---
 arch/c6x/kernel/Makefile       |   13 +
 arch/c6x/kernel/asm-offsets.c  |  127 ++++++
 arch/c6x/kernel/c6x_ksyms.c    |   75 ++++
 arch/c6x/kernel/clkdev.c       |  192 +++++++++
 arch/c6x/kernel/early_printk.c |   81 ++++
 arch/c6x/kernel/entry.S        |  851 ++++++++++++++++++++++++++++++++++++++++
 arch/c6x/kernel/head.S         |  127 ++++++
 arch/c6x/kernel/irq.c          |  119 ++++++
 arch/c6x/kernel/module.c       |  249 ++++++++++++
 arch/c6x/kernel/process.c      |  349 ++++++++++++++++
 arch/c6x/kernel/ptrace.c       |  284 +++++++++++++
 arch/c6x/kernel/setup.c        |  550 ++++++++++++++++++++++++++
 arch/c6x/kernel/signal.c       |  384 ++++++++++++++++++
 arch/c6x/kernel/switch_to.S    |   67 ++++
 arch/c6x/kernel/sys_c6x.c      |  111 ++++++
 arch/c6x/kernel/tags.c         |   98 +++++
 arch/c6x/kernel/tags.h         |   82 ++++
 arch/c6x/kernel/time.c         |   55 +++
 arch/c6x/kernel/traps.c        |  416 ++++++++++++++++++++
 arch/c6x/kernel/vectors.S      |   81 ++++
 arch/c6x/kernel/vmlinux.lds.S  |  205 ++++++++++
 21 files changed, 4516 insertions(+), 0 deletions(-)
 create mode 100644 arch/c6x/kernel/Makefile
 create mode 100644 arch/c6x/kernel/asm-offsets.c
 create mode 100644 arch/c6x/kernel/c6x_ksyms.c
 create mode 100644 arch/c6x/kernel/clkdev.c
 create mode 100644 arch/c6x/kernel/early_printk.c
 create mode 100644 arch/c6x/kernel/entry.S
 create mode 100644 arch/c6x/kernel/head.S
 create mode 100644 arch/c6x/kernel/irq.c
 create mode 100644 arch/c6x/kernel/module.c
 create mode 100644 arch/c6x/kernel/process.c
 create mode 100644 arch/c6x/kernel/ptrace.c
 create mode 100644 arch/c6x/kernel/setup.c
 create mode 100644 arch/c6x/kernel/signal.c
 create mode 100644 arch/c6x/kernel/switch_to.S
 create mode 100644 arch/c6x/kernel/sys_c6x.c
 create mode 100644 arch/c6x/kernel/tags.c
 create mode 100644 arch/c6x/kernel/tags.h
 create mode 100644 arch/c6x/kernel/time.c
 create mode 100644 arch/c6x/kernel/traps.c
 create mode 100644 arch/c6x/kernel/vectors.S
 create mode 100644 arch/c6x/kernel/vmlinux.lds.S

diff --git a/arch/c6x/kernel/Makefile b/arch/c6x/kernel/Makefile
new file mode 100644
index 0000000..25cdded
--- /dev/null
+++ b/arch/c6x/kernel/Makefile
@@ -0,0 +1,13 @@
+#
+# Makefile for arch/c6x/kernel/
+#
+
+extra-y	 := head.o vmlinux.lds
+
+obj-y 	 := process.o traps.o irq.o signal.o ptrace.o \
+	    setup.o sys_c6x.o time.o \
+            switch_to.o entry.o vectors.o c6x_ksyms.o tags.o
+
+obj-$(CONFIG_MODULES)          += module.o
+obj-$(CONFIG_COMMON_CLKDEV)    += clkdev.o
+obj-$(CONFIG_EARLY_PRINTK)     += early_printk.o
diff --git a/arch/c6x/kernel/asm-offsets.c b/arch/c6x/kernel/asm-offsets.c
new file mode 100644
index 0000000..52fca25
--- /dev/null
+++ b/arch/c6x/kernel/asm-offsets.c
@@ -0,0 +1,127 @@
+/*
+ * Generate definitions needed by assembly language modules.
+ * This code generates raw asm output which is post-processed
+ * to extract and format the required data.
+ */
+
+#include <linux/types.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/dma-mapping.h>
+#include <linux/thread_info.h>
+#include <asm/procinfo.h>
+#include <linux/kbuild.h>
+#include <linux/unistd.h>
+
+void foo(void)
+{
+	OFFSET(REGS_A16,	pt_regs, a16);
+	OFFSET(REGS_A17,	pt_regs, a17);
+	OFFSET(REGS_A18,	pt_regs, a18);
+	OFFSET(REGS_A19,	pt_regs, a19);
+	OFFSET(REGS_A20,	pt_regs, a20);
+	OFFSET(REGS_A21,	pt_regs, a21);
+	OFFSET(REGS_A22,	pt_regs, a22);
+	OFFSET(REGS_A23,	pt_regs, a23);
+	OFFSET(REGS_A24,	pt_regs, a24);
+	OFFSET(REGS_A25,	pt_regs, a25);
+	OFFSET(REGS_A26,	pt_regs, a26);
+	OFFSET(REGS_A27,	pt_regs, a27);
+	OFFSET(REGS_A28,	pt_regs, a28);
+	OFFSET(REGS_A29,	pt_regs, a29);
+	OFFSET(REGS_A30,	pt_regs, a30);
+	OFFSET(REGS_A31,	pt_regs, a31);
+
+	OFFSET(REGS_B16,	pt_regs, b16);
+	OFFSET(REGS_B17,	pt_regs, b17);
+	OFFSET(REGS_B18,	pt_regs, b18);
+	OFFSET(REGS_B19,	pt_regs, b19);
+	OFFSET(REGS_B20,	pt_regs, b20);
+	OFFSET(REGS_B21,	pt_regs, b21);
+	OFFSET(REGS_B22,	pt_regs, b22);
+	OFFSET(REGS_B23,	pt_regs, b23);
+	OFFSET(REGS_B24,	pt_regs, b24);
+	OFFSET(REGS_B25,	pt_regs, b25);
+	OFFSET(REGS_B26,	pt_regs, b26);
+	OFFSET(REGS_B27,	pt_regs, b27);
+	OFFSET(REGS_B28,	pt_regs, b28);
+	OFFSET(REGS_B29,	pt_regs, b29);
+	OFFSET(REGS_B30,	pt_regs, b30);
+	OFFSET(REGS_B31,	pt_regs, b31);
+
+	OFFSET(REGS_A0,		pt_regs, a0);
+	OFFSET(REGS_A1,		pt_regs, a1);
+	OFFSET(REGS_A2,		pt_regs, a2);
+	OFFSET(REGS_A3,		pt_regs, a3);
+	OFFSET(REGS_A4,		pt_regs, a4);
+	OFFSET(REGS_A5,		pt_regs, a5);
+	OFFSET(REGS_A6,		pt_regs, a6);
+	OFFSET(REGS_A7,		pt_regs, a7);
+	OFFSET(REGS_A8,		pt_regs, a8);
+	OFFSET(REGS_A9,		pt_regs, a9);
+	OFFSET(REGS_A10,	pt_regs, a10);
+	OFFSET(REGS_A11,	pt_regs, a11);
+	OFFSET(REGS_A12,	pt_regs, a12);
+	OFFSET(REGS_A13,	pt_regs, a13);
+	OFFSET(REGS_A14,	pt_regs, a14);
+	OFFSET(REGS_A15,	pt_regs, a15);
+
+	OFFSET(REGS_B0,		pt_regs, b0);
+	OFFSET(REGS_B1,		pt_regs, b1);
+	OFFSET(REGS_B2,		pt_regs, b2);
+	OFFSET(REGS_B3,		pt_regs, b3);
+	OFFSET(REGS_B4,		pt_regs, b4);
+	OFFSET(REGS_B5,		pt_regs, b5);
+	OFFSET(REGS_B6,		pt_regs, b6);
+	OFFSET(REGS_B7,		pt_regs, b7);
+	OFFSET(REGS_B8,		pt_regs, b8);
+	OFFSET(REGS_B9,		pt_regs, b9);
+	OFFSET(REGS_B10,	pt_regs, b10);
+	OFFSET(REGS_B11,	pt_regs, b11);
+	OFFSET(REGS_B12,	pt_regs, b12);
+	OFFSET(REGS_B13,	pt_regs, b13);
+	OFFSET(REGS_DP,		pt_regs, dp);
+	OFFSET(REGS_SP,		pt_regs, sp);
+
+	OFFSET(REGS_TSR,	pt_regs, tsr);
+	OFFSET(REGS_ORIG_A4,	pt_regs, orig_a4);
+
+	DEFINE(REGS__END,	sizeof(struct pt_regs));
+	BLANK();
+
+	OFFSET(THREAD_PC,	thread_struct, pc);
+	OFFSET(THREAD_B15_14,	thread_struct, b15_14);
+	OFFSET(THREAD_A15_14,	thread_struct, a15_14);
+	OFFSET(THREAD_B13_12,	thread_struct, b13_12);
+	OFFSET(THREAD_A13_12,	thread_struct, a13_12);
+	OFFSET(THREAD_B11_10,	thread_struct, b11_10);
+	OFFSET(THREAD_A11_10,	thread_struct, a11_10);
+	OFFSET(THREAD_RICL_ICL,	thread_struct, ricl_icl);
+	BLANK();
+
+	OFFSET(TASK_STATE,	task_struct, state);
+	BLANK();
+
+	OFFSET(THREAD_INFO_FLAGS,	thread_info, flags);
+	OFFSET(THREAD_INFO_PREEMPT_COUNT, thread_info, preempt_count);
+	BLANK();
+
+	/* These would be unneccessary if we ran asm files
+	 * through the preprocessor.
+	 */
+	DEFINE(KTHREAD_SIZE, THREAD_SIZE);
+	DEFINE(KTHREAD_SHIFT, THREAD_SHIFT);
+	DEFINE(KTHREAD_START_SP, THREAD_START_SP);
+	DEFINE(ENOSYS_, ENOSYS);
+	DEFINE(NR_SYSCALLS_, __NR_syscalls);
+
+	DEFINE(_TIF_SYSCALL_TRACE, (1<<TIF_SYSCALL_TRACE));
+	DEFINE(_TIF_NOTIFY_RESUME, (1<<TIF_NOTIFY_RESUME));
+	DEFINE(_TIF_SIGPENDING, (1<<TIF_SIGPENDING));
+	DEFINE(_TIF_NEED_RESCHED, (1<<TIF_NEED_RESCHED));
+	DEFINE(_TIF_POLLING_NRFLAG, (1<<TIF_POLLING_NRFLAG));
+
+	DEFINE(_TIF_ALLWORK_MASK, TIF_ALLWORK_MASK);
+	DEFINE(_TIF_WORK_MASK, TIF_WORK_MASK);
+}
+
diff --git a/arch/c6x/kernel/c6x_ksyms.c b/arch/c6x/kernel/c6x_ksyms.c
new file mode 100644
index 0000000..8ee8a93
--- /dev/null
+++ b/arch/c6x/kernel/c6x_ksyms.c
@@ -0,0 +1,75 @@
+/*
+ *  linux/arch/c6x/kernel/c6x_ksyms.c
+ *
+ *  Port on Texas Instruments TMS320C6x architecture
+ *
+ *  Copyright (C) 2004, 2009, 2010, 2011 Texas Instruments Incorporated
+ *  Author: Aurelien Jacquiot (aurelien.jacquiot@...una.com)
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ *
+ */
+#include <linux/module.h>
+#include <asm/checksum.h>
+#include <linux/io.h>
+
+/*
+ * libgcc functions - used internally by the compiler...
+ */
+extern int __c6xabi_divi(int dividend, int divisor);
+EXPORT_SYMBOL(__c6xabi_divi);
+
+extern unsigned __c6xabi_divu(unsigned	dividend, unsigned divisor);
+EXPORT_SYMBOL(__c6xabi_divu);
+
+extern int __c6xabi_remi(int dividend, int divisor);
+EXPORT_SYMBOL(__c6xabi_remi);
+
+extern unsigned __c6xabi_remu(unsigned	dividend, unsigned divisor);
+EXPORT_SYMBOL(__c6xabi_remu);
+
+extern int __c6xabi_divremi(int dividend, int divisor);
+EXPORT_SYMBOL(__c6xabi_divremi);
+
+extern unsigned __c6xabi_divremu(unsigned  dividend, unsigned divisor);
+EXPORT_SYMBOL(__c6xabi_divremu);
+
+extern unsigned long long __c6xabi_mpyll(unsigned long long src1,
+					 unsigned long long src2);
+EXPORT_SYMBOL(__c6xabi_mpyll);
+
+extern unsigned long long __c6xabi_divull(unsigned long long n,
+					  unsigned long long d);
+EXPORT_SYMBOL(__c6xabi_divull);
+
+extern long long __c6xabi_negll(long long src);
+EXPORT_SYMBOL(__c6xabi_negll);
+
+extern unsigned long long __c6xabi_llshl(unsigned long long src1, uint src2);
+EXPORT_SYMBOL(__c6xabi_llshl);
+
+extern long long __c6xabi_llshr(long long src1, uint src2);
+EXPORT_SYMBOL(__c6xabi_llshr);
+
+extern unsigned long long __c6xabi_llshru(unsigned long long src1, uint src2);
+EXPORT_SYMBOL(__c6xabi_llshru);
+
+extern void __c6xabi_strasgi(int *dst, const int *src, unsigned cnt);
+EXPORT_SYMBOL(__c6xabi_strasgi);
+
+extern void __c6xabi_push_rts(void);
+EXPORT_SYMBOL(__c6xabi_push_rts);
+
+extern void __c6xabi_pop_rts(void);
+EXPORT_SYMBOL(__c6xabi_pop_rts);
+
+extern void __c6xabi_strasgi_64plus(int *dst, const int *src, unsigned cnt);
+EXPORT_SYMBOL(__c6xabi_strasgi_64plus);
+
+/* lib functions */
+EXPORT_SYMBOL(memcpy);
+EXPORT_SYMBOL(csum_partial);
+EXPORT_SYMBOL(ip_fast_csum);
+
diff --git a/arch/c6x/kernel/clkdev.c b/arch/c6x/kernel/clkdev.c
new file mode 100644
index 0000000..747c316
--- /dev/null
+++ b/arch/c6x/kernel/clkdev.c
@@ -0,0 +1,192 @@
+/*
+ *  arch/c6x/kernel/clkdev.c
+ *
+ *  Copyright (C) 2010 Texas Instruments Incorporated
+ *  Author: Mark Salter <msalter@...hat.com>
+ *
+ *  Original code from: arch/arm/common/clkdev.c
+ *
+ *  Copyright (C) 2008 Russell King.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Helper for the clk API to assist looking up a struct clk.
+ */
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <linux/list.h>
+#include <linux/errno.h>
+#include <linux/err.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+#include <linux/mutex.h>
+#include <linux/clk.h>
+
+#include <asm/clkdev.h>
+
+static LIST_HEAD(clocks);
+static DEFINE_MUTEX(clocks_mutex);
+
+
+int __weak __clk_get(struct clk *clk)
+{
+	return 1;
+}
+
+void __weak __clk_put(struct clk *clk)
+{
+}
+
+/*
+ * Find the correct struct clk for the device and connection ID.
+ * We do slightly fuzzy matching here:
+ *  An entry with a NULL ID is assumed to be a wildcard.
+ *  If an entry has a device ID, it must match
+ *  If an entry has a connection ID, it must match
+ * Then we take the most specific entry - with the following
+ * order of precedence: dev+con > dev only > con only.
+ */
+static struct clk *clk_find(const char *dev_id, const char *con_id)
+{
+	struct clk_lookup *p;
+	struct clk *clk = NULL;
+	int match, best = 0;
+
+	list_for_each_entry(p, &clocks, node) {
+		match = 0;
+		if (p->dev_id) {
+			if (!dev_id || strcmp(p->dev_id, dev_id))
+				continue;
+			match += 2;
+		}
+		if (p->con_id) {
+			if (!con_id || strcmp(p->con_id, con_id))
+				continue;
+			match += 1;
+		}
+		if (match == 0)
+			continue;
+
+		if (match > best) {
+			clk = p->clk;
+			best = match;
+		}
+	}
+	return clk;
+}
+
+struct clk *clk_get_sys(const char *dev_id, const char *con_id)
+{
+	struct clk *clk;
+
+	mutex_lock(&clocks_mutex);
+	clk = clk_find(dev_id, con_id);
+	if (clk && !__clk_get(clk))
+		clk = NULL;
+	mutex_unlock(&clocks_mutex);
+
+	return clk ? clk : ERR_PTR(-ENOENT);
+}
+EXPORT_SYMBOL(clk_get_sys);
+
+struct clk *clk_get(struct device *dev, const char *con_id)
+{
+	const char *dev_id = dev ? dev_name(dev) : NULL;
+
+	return clk_get_sys(dev_id, con_id);
+}
+EXPORT_SYMBOL(clk_get);
+
+void clk_put(struct clk *clk)
+{
+	__clk_put(clk);
+}
+EXPORT_SYMBOL(clk_put);
+
+void clkdev_add(struct clk_lookup *cl)
+{
+	mutex_lock(&clocks_mutex);
+	list_add_tail(&cl->node, &clocks);
+	mutex_unlock(&clocks_mutex);
+}
+EXPORT_SYMBOL(clkdev_add);
+
+void __init clkdev_add_table(struct clk_lookup *cl, size_t num)
+{
+	mutex_lock(&clocks_mutex);
+	while (num--) {
+		list_add_tail(&cl->node, &clocks);
+		cl++;
+	}
+	mutex_unlock(&clocks_mutex);
+}
+
+#define MAX_DEV_ID	20
+#define MAX_CON_ID	16
+
+struct clk_lookup_alloc {
+	struct clk_lookup cl;
+	char	dev_id[MAX_DEV_ID];
+	char	con_id[MAX_CON_ID];
+};
+
+struct clk_lookup *clkdev_alloc(struct clk *clk, const char *con_id,
+	const char *dev_fmt, ...)
+{
+	struct clk_lookup_alloc *cla;
+
+	cla = kzalloc(sizeof(*cla), GFP_KERNEL);
+	if (!cla)
+		return NULL;
+
+	cla->cl.clk = clk;
+	if (con_id) {
+		strlcpy(cla->con_id, con_id, sizeof(cla->con_id));
+		cla->cl.con_id = cla->con_id;
+	}
+
+	if (dev_fmt) {
+		va_list ap;
+
+		va_start(ap, dev_fmt);
+		vscnprintf(cla->dev_id, sizeof(cla->dev_id), dev_fmt, ap);
+		cla->cl.dev_id = cla->dev_id;
+		va_end(ap);
+	}
+
+	return &cla->cl;
+}
+EXPORT_SYMBOL(clkdev_alloc);
+
+int clk_add_alias(const char *alias, const char *alias_dev_name, char *id,
+	struct device *dev)
+{
+	struct clk *r = clk_get(dev, id);
+	struct clk_lookup *l;
+
+	if (IS_ERR(r))
+		return PTR_ERR(r);
+
+	l = clkdev_alloc(r, alias, alias_dev_name);
+	clk_put(r);
+	if (!l)
+		return -ENODEV;
+	clkdev_add(l);
+	return 0;
+}
+EXPORT_SYMBOL(clk_add_alias);
+
+/*
+ * clkdev_drop - remove a clock dynamically allocated
+ */
+void clkdev_drop(struct clk_lookup *cl)
+{
+	mutex_lock(&clocks_mutex);
+	list_del(&cl->node);
+	mutex_unlock(&clocks_mutex);
+	kfree(cl);
+}
+EXPORT_SYMBOL(clkdev_drop);
diff --git a/arch/c6x/kernel/early_printk.c b/arch/c6x/kernel/early_printk.c
new file mode 100644
index 0000000..06a72fd
--- /dev/null
+++ b/arch/c6x/kernel/early_printk.c
@@ -0,0 +1,81 @@
+/*
+ *  linux/arch/c6x/kernel/early_printk.c
+ *
+ *  Copyright (C) 2011 Texas Instruments Incoporated
+ *  Author: Mark Salter <msalter@...hat.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/console.h>
+#include <linux/init.h>
+#include <linux/string.h>
+#include <asm/setup.h>
+
+
+static void (*early_write)(const char *s, unsigned n);
+
+static int __initdata keep_early;
+
+static void early_console_write(struct console *con, const char *s, unsigned n)
+{
+	early_write(s, n);
+}
+
+static struct console early_console = {
+	.write =	early_console_write,
+	.flags =	CON_PRINTBUFFER,
+	.index =	-1,
+};
+
+void early_printk(const char *fmt, ...)
+{
+	char buf[512];
+	int n;
+	va_list ap;
+
+	va_start(ap, fmt);
+	n = vscnprintf(buf, sizeof(buf), fmt, ap);
+	early_write(buf, n);
+	va_end(ap);
+}
+
+static int __init setup_early_printk(char *str)
+{
+	if (!str)
+		return 0;
+
+	if (early_write != NULL)
+		return 0;
+
+#ifdef CONFIG_HVC_C6X
+	if (!strncmp(str, "hvc", 3)) {
+		str += 3;
+		early_write = hvc_c6x_early_puts;
+		strcpy(early_console.name, "early_hvc");
+	}
+#endif
+
+	if (strncmp(str, ",keep", 5) == 0)
+		keep_early = 1;
+
+	if (likely(early_write)) {
+
+		if (keep_early)
+			early_console.flags &= ~CON_BOOT;
+		else
+			early_console.flags |= CON_BOOT;
+
+		register_console(&early_console);
+		printk(KERN_INFO "early printk enabled on %s%d\n",
+			early_console.name,
+			early_console.index);
+	}
+
+	return 0;
+}
+early_param("earlyprintk", setup_early_printk);
+
diff --git a/arch/c6x/kernel/entry.S b/arch/c6x/kernel/entry.S
new file mode 100644
index 0000000..e35dd2d
--- /dev/null
+++ b/arch/c6x/kernel/entry.S
@@ -0,0 +1,851 @@
+;
+;  linux/arch/c6x/kernel/entry.s
+;
+;  Port on Texas Instruments TMS320C6x architecture
+;
+;  Copyright (C) 2004, 2005, 2006, 2009, 2010, 2011 Texas Instruments Incorporated
+;  Author: Aurelien Jacquiot (aurelien.jacquiot@...tuallogix.com)
+;  Updated for 2.6.34: Mark Salter <msalter@...hat.com>
+;
+;  This program is free software; you can redistribute it and/or modify
+;  it under the terms of the GNU General Public License version 2 as
+;  published by the Free Software Foundation.
+;
+
+	.altmacro
+#define _DEFINE_MACRO(name,args...) .macro name args
+
+#include <linux/sys.h>
+#include <linux/linkage.h>
+#include <asm/thread_info.h>
+#include <asm/asm-offsets.h>
+#include <asm/unistd.h>
+#include <asm/errno.h>
+
+; Registers naming
+#define DP	B14
+#define SP	B15
+
+#ifndef CONFIG_PREEMPT
+#define resume_kernel restore_all
+#endif
+
+	;; Entry management functions
+		.global	ret_from_exception
+		.global	ret_from_interrupt
+
+	;; Interrupt handlers
+		.global	_int4_handler
+		.global	_int5_handler
+		.global	_int6_handler
+		.global	_int7_handler
+		.global	_int8_handler
+		.global	_int9_handler
+		.global	_int10_handler
+		.global	_int11_handler
+		.global	_int12_handler
+		.global	_int13_handler
+		.global	_int14_handler
+		.global	_int15_handler
+		.global	_bad_interrupt
+		.global	_nmi_handler
+
+	;;
+	;;  This defines the normal kernel pt_regs layout.
+	;;
+_DEFINE_MACRO(SAVE_ALL,__rp,__tsr)
+	STW	.D2T2	B0,*SP--[2]		; save original B0
+	MVKL	.S2	current_ksp,B0
+	MVKH	.S2	current_ksp,B0
+	LDW	.D2T2	*B0,B1			; KSP
+
+	NOP	3
+	STW	.D2T2	B1,*+SP[1]		; save original B1
+	XOR	.D2	SP,B1,B0		; (SP ^ KSP)
+	LDW	.D2T2	*+SP[1],B1		; restore B0/B1
+	LDW	.D2T2	*++SP[2],B0
+	SHR	.S2	B0,THREAD_SHIFT,B0	; 0 if already using kernel stack
+
+  [B0]	STDW	.D2T2	SP:DP,*--B1[1]		; user: save user sp/dp on kernel stack
+  [B0]	MV	.S2	B1,SP			;    and switch to kernel stack
+||[!B0] STDW	.D2T2	SP:DP,*--SP[1]		; kernel: save on current stack
+
+	SUBAW	.D2	SP,2,SP
+
+	ADD	.D1X	SP,-8,A15
+ ||	STDW	.D2T1	A15:A14,*SP--[16]	; save A15:A14
+
+	STDW	.D2T2	B13:B12,*SP--[1]
+ ||	STDW	.D1T1	A13:A12,*A15--[1]
+ ||	MVC	.S2	__rp,B13
+
+	STDW	.D2T2	B11:B10,*SP--[1]
+ ||	STDW	.D1T1	A11:A10,*A15--[1]
+ ||	MVC	.S2	CSR,B12
+
+	STDW	.D2T2	B9:B8,*SP--[1]
+ ||	STDW	.D1T1	A9:A8,*A15--[1]
+ ||	MVC	.S2	RILC,B11
+	STDW	.D2T2	B7:B6,*SP--[1]
+ ||	STDW	.D1T1	A7:A6,*A15--[1]
+ ||	MVC	.S2	ILC,B10
+
+	STDW	.D2T2	B5:B4,*SP--[1]
+ ||	STDW	.D1T1	A5:A4,*A15--[1]
+
+	STDW	.D2T2	B3:B2,*SP--[1]
+ ||	STDW	.D1T1	A3:A2,*A15--[1]
+ ||	MVC	.S2	__tsr,B5
+
+	STDW	.D2T2	B1:B0,*SP--[1]
+ ||	STDW	.D1T1	A1:A0,*A15--[1]
+ ||	MV	.S1X	B5,A5
+
+	STDW	.D2T2	B31:B30,*SP--[1]
+ ||	STDW	.D1T1	A31:A30,*A15--[1]
+	STDW	.D2T2	B29:B28,*SP--[1]
+ ||	STDW	.D1T1	A29:A28,*A15--[1]
+	STDW	.D2T2	B27:B26,*SP--[1]
+ ||	STDW	.D1T1	A27:A26,*A15--[1]
+	STDW	.D2T2	B25:B24,*SP--[1]
+ ||	STDW	.D1T1	A25:A24,*A15--[1]
+	STDW	.D2T2	B23:B22,*SP--[1]
+ ||	STDW	.D1T1	A23:A22,*A15--[1]
+	STDW	.D2T2	B21:B20,*SP--[1]
+ ||	STDW	.D1T1	A21:A20,*A15--[1]
+	STDW	.D2T2	B19:B18,*SP--[1]
+ ||	STDW	.D1T1	A19:A18,*A15--[1]
+	STDW	.D2T2	B17:B16,*SP--[1]
+ ||	STDW	.D1T1	A17:A16,*A15--[1]
+
+	STDW	.D2T2	B13:B12,*SP--[1]	; save PC and CSR
+
+	STDW	.D2T2	B11:B10,*SP--[1]	; save RILC and ILC
+	STDW	.D2T1	A5:A4,*SP--[1]		; save TSR and orig A4
+
+	;; We left an unused word on the stack just above pt_regs.
+	;; It is used to save whether or not this frame is due to
+	;; a syscall. It is cleared here, but the syscall handler
+	;; sets it to a non-zero value.
+	MVK	.L2	0,B1
+	STW	.D2T2	B1,*+SP(REGS__END+8)	; clear syscall flag
+	.endm
+
+_DEFINE_MACRO(SAVE_ALL_EXCEPT)
+	SAVE_ALL NRP,NTSR
+	.endm
+
+_DEFINE_MACRO(SAVE_ALL_INT)
+	SAVE_ALL IRP,ITSR
+	.endm
+
+_DEFINE_MACRO(RESTORE_ALL,__rp,__tsr)
+
+	LDDW	.D2T2	*++SP[1],B9:B8		; get TSR (B9)
+	LDDW	.D2T2	*++SP[1],B11:B10	; get RILC (B11) and ILC (B10)
+	LDDW	.D2T2	*++SP[1],B13:B12	; get PC (B13) and CSR (B12)
+
+	ADDAW	.D1X	SP,30,A15
+
+	LDDW	.D1T1	*++A15[1],A17:A16
+ ||	LDDW	.D2T2	*++SP[1],B17:B16
+	LDDW	.D1T1	*++A15[1],A19:A18
+ ||	LDDW	.D2T2	*++SP[1],B19:B18
+	LDDW	.D1T1	*++A15[1],A21:A20
+ ||	LDDW	.D2T2	*++SP[1],B21:B20
+	LDDW	.D1T1	*++A15[1],A23:A22
+ ||	LDDW	.D2T2	*++SP[1],B23:B22
+	LDDW	.D1T1	*++A15[1],A25:A24
+ ||	LDDW	.D2T2	*++SP[1],B25:B24
+	LDDW	.D1T1	*++A15[1],A27:A26
+ ||	LDDW	.D2T2	*++SP[1],B27:B26
+	LDDW	.D1T1	*++A15[1],A29:A28
+ ||	LDDW	.D2T2	*++SP[1],B29:B28
+	LDDW	.D1T1	*++A15[1],A31:A30
+ ||	LDDW	.D2T2	*++SP[1],B31:B30
+
+	LDDW	.D1T1	*++A15[1],A1:A0
+ ||	LDDW	.D2T2	*++SP[1],B1:B0
+
+	LDDW	.D1T1	*++A15[1],A3:A2
+ ||	LDDW	.D2T2	*++SP[1],B3:B2
+ ||	MVC	.S2	B9,__tsr
+	LDDW	.D1T1	*++A15[1],A5:A4
+ ||	LDDW	.D2T2	*++SP[1],B5:B4
+ ||	MVC	.S2	B11,RILC
+	LDDW	.D1T1	*++A15[1],A7:A6
+ ||	LDDW	.D2T2	*++SP[1],B7:B6
+ ||	MVC	.S2	B10,ILC
+
+	LDDW	.D1T1	*++A15[1],A9:A8
+ ||	LDDW	.D2T2	*++SP[1],B9:B8
+ ||	MVC	.S2	B13,__rp
+
+	LDDW	.D1T1	*++A15[1],A11:A10
+ ||	LDDW	.D2T2	*++SP[1],B11:B10
+ ||	MVC	.S2	B12,CSR
+
+	LDDW	.D1T1	*++A15[1],A13:A12
+ ||	LDDW	.D2T2	*++SP[1],B13:B12
+
+	MV	.D2X	A15,SP
+ ||	MVKL	.S1	current_ksp,A15
+	MVKH	.S1	current_ksp,A15
+ ||	ADDAW	.D1X	SP,6,A14
+	STW	.D1T1	A14,*A15	; save kernel stack pointer
+
+	LDDW	.D2T1	*++SP[1],A15:A14
+
+	B	.S2	__rp		; return from interruption
+	LDDW	.D2T2	*+SP[1],SP:DP
+	NOP	4
+	.endm
+
+_DEFINE_MACRO(RESTORE_ALL_EXCEPT)
+	RESTORE_ALL NRP,NTSR
+	.endm
+
+_DEFINE_MACRO(RESTORE_ALL_INT)
+	RESTORE_ALL IRP,ITSR
+	.endm
+
+_DEFINE_MACRO(MASK_SYSCALL)
+	.endm
+
+_DEFINE_MACRO(UNMASK_SYSCALL)
+	.endm
+
+_DEFINE_MACRO(MASK_INT,reg)
+	MVC	.S2	CSR,reg
+	CLR	.S2	reg,0,0,reg
+	MVC	.S2	reg,CSR
+	.endm
+
+	;; Enable interrupts
+_DEFINE_MACRO(UNMASK_INT,reg)
+	MVC	.S2	CSR,reg
+	SET	.S2	reg,0,0,reg
+	MVC	.S2	reg,CSR
+	.endm
+
+	;;
+	;; Call c6x_do_IRQ with the corresponding int number and regs
+	;;
+_DEFINE_MACRO(CALL_INT,int)
+#ifdef CONFIG_BIG_KERNEL
+	MVKL	.S1	c6x_do_IRQ,A0
+	MVKH	.S1	c6x_do_IRQ,A0
+	BNOP	.S2X	A0,1
+	MVK	.S1	int,A4
+	ADDAW	.D2	SP,2,B4
+	MVKL	.S2	ret_from_interrupt,B3
+	MVKH	.S2	ret_from_interrupt,B3
+#else
+	CALLP   .S2	c6x_do_IRQ,B3
+ ||	MVK	.S1	int,A4
+ ||	ADDAW	.D2	SP,2,B4
+	B	.S1	ret_from_interrupt
+	NOP	5
+#endif
+	.endm
+
+_DEFINE_MACRO(GET_THREAD_INFO,reg)
+	SHR	.S1X	SP,THREAD_SHIFT,reg
+	SHL	.S1	reg,THREAD_SHIFT,reg
+	.endm
+
+	.sect	".data"
+
+	.global	current_ksp
+current_ksp:
+	.word	init_thread_union + THREAD_START_SP
+
+	.sect	".text"
+
+	;;
+	;; Jump to schedule() then return to ret_from_exception
+	;;
+_reschedule:
+#ifdef CONFIG_BIG_KERNEL
+	MVKL	.S1	schedule,A0
+	MVKH	.S1	schedule,A0
+	B	.S2X	A0
+#else
+	B	.S1	schedule
+#endif
+	ADDKPC	.S2	ret_from_exception,B3,4
+
+	;;
+	;; Called before syscall handler when process is being debugged
+	;;
+tracesys_on:
+#ifdef CONFIG_BIG_KERNEL
+	MVKL	.S1	syscall_trace_entry,A0
+	MVKH	.S1	syscall_trace_entry,A0
+	B	.S2X	A0
+#else
+	B	.S1	syscall_trace_entry
+#endif
+	ADDKPC	.S2	ret_from_syscall_trace,B3,3
+	ADD	.S1X	8,SP,A4
+
+ret_from_syscall_trace:
+	;; tracing returns (possibly new) syscall number
+	MV	.D2X	A4,B0
+ ||	MVK	.S2	__NR_syscalls,B1
+	CMPLTU	.L2	B0,B1,B1
+
+ [!B1]	BNOP	.S2	ret_from_syscall_function,5
+ ||	MVK	.S1	-ENOSYS,A4
+
+	;; reload syscall args from (possibly modified) stack frame
+	LDW	.D2T2	*+SP(REGS_B4+8),B4
+	LDW	.D2T1	*+SP(REGS_A6+8),A6
+	LDW	.D2T2	*+SP(REGS_B6+8),B6
+	LDW	.D2T1	*+SP(REGS_A8+8),A8
+	LDW	.D2T2	*+SP(REGS_B8+8),B8
+
+	;; Get syscall handler addr from sys_call_table:
+	MVKL	.S2	sys_call_table,B1
+	MVKH	.S2	sys_call_table,B1
+	LDW	.D2T2	*+B1[B0],B0		; B0 = sys_call_table[__NR_*]
+	MVKL	.S2	ret_from_syscall_function,B3
+	MVKH	.S2	ret_from_syscall_function,B3
+	NOP	2
+	BNOP	.S2	B0,5			; branch to syscall handler
+ ||	LDW	.D2T1	*+SP(REGS_ORIG_A4+8),A4
+
+syscall_exit_work:
+	AND	.D1	_TIF_SYSCALL_TRACE,A2,A0
+ [!A0]	BNOP	.S1	work_pending,5
+ [A0]	B	.S2	syscall_trace_exit
+	ADDKPC	.S2	resume_userspace,B3,1
+	MVC	.S2	CSR,B1
+	SET	.S2	B1,0,0,B1
+	MVC	.S2	B1,CSR		; enable ints
+
+work_pending:
+	AND	.D1	_TIF_NEED_RESCHED,A2,A0
+ [!A0]	BNOP	.S1	work_notifysig,5
+
+work_resched:
+#ifdef CONFIG_BIG_KERNEL
+	MVKL	.S1	schedule,A1
+	MVKH	.S1	schedule,A1
+	B	.S2X	A1
+#else
+	B	.S2	schedule
+#endif
+	ADDKPC	.S2	work_rescheduled,B3,4
+work_rescheduled:
+	;; make sure we don't miss an interrupt setting need_resched or
+	;; sigpending between sampling and the rti
+	MASK_INT B2
+	GET_THREAD_INFO A12
+	LDW	.D1T1	*+A12(THREAD_INFO_FLAGS),A2
+	MVK	.S1	_TIF_WORK_MASK,A1
+	MVK	.S1	_TIF_NEED_RESCHED,A3
+	NOP	2
+	AND	.D1	A1,A2,A0
+ ||	AND	.S1	A3,A2,A1
+ [!A0]	BNOP	.S1	restore_all,5
+ [A1]	BNOP	.S1	work_resched,5
+
+work_notifysig:
+	B	.S2	do_notify_resume
+	LDW	.D2T1	*+SP(REGS__END+8),A6 ; syscall flag
+	ADDKPC	.S2	resume_userspace,B3,1
+	ADD	.S1X	8,SP,A4		; pt_regs pointer is first arg
+	MV	.D2X	A2,B4		; thread_info flags is second arg
+
+ret_from_exception:
+#ifdef CONFIG_PREEMPT
+	MASK_INT B2
+#endif
+	;;
+	;; On C64x+, the return way from exception and interrupt
+	;; is a little bit different
+	;;
+ret_from_interrupt:
+	;;
+	;; Check if we are comming from user mode.
+	;;
+	LDW	.D2T2	*+SP(REGS_TSR+8),B0
+	MVK	.S2	0x40,B1
+	NOP	3
+	AND	.D2	B0,B1,B0
+ [!B0]	BNOP	.S2	resume_kernel,5
+
+resume_userspace:
+	;; make sure we don't miss an interrupt setting need_resched or
+	;; sigpending between sampling and the rti
+	MASK_INT B2
+	GET_THREAD_INFO A12
+	LDW	.D1T1	*+A12(THREAD_INFO_FLAGS),A2
+	MVK	.S1	_TIF_WORK_MASK,A1
+	MVK	.S1	_TIF_NEED_RESCHED,A3
+	NOP	2
+	AND	.D1	A1,A2,A0
+ [A0]	BNOP	.S1	work_pending,5
+	BNOP	.S1	restore_all,5
+
+	;;
+	;; System call handling
+	;; B0 = syscall number (in sys_call_table)
+	;; A4,B4,A6,B6,A8,B8 = arguments of the syscall function
+	;; A4 is the return value register
+	;;
+system_call_saved:
+	MVK	.L2	1,B2
+	STW	.D2T2	B2,*+SP(REGS__END+8)	; set syscall flag
+	MVC	.S2	B2,ECR			; acknowledge the software exception
+
+	UNMASK_INT B2			; re-enable global IT
+
+system_call_saved_noack:
+	;; Check system call number
+	MVK	.S2	__NR_syscalls,B1
+#ifdef CONFIG_BIG_KERNEL
+ ||	MVKL	.S1	sys_ni_syscall,A0
+#endif
+	CMPLTU	.L2	B0,B1,B1
+#ifdef CONFIG_BIG_KERNEL
+ ||	MVKH	.S1	sys_ni_syscall,A0
+#endif
+
+	;; Check for ptrace
+	GET_THREAD_INFO A12
+
+#ifdef CONFIG_BIG_KERNEL
+ [!B1]	B	.S2X	A0
+#else
+ [!B1]	B	.S2	sys_ni_syscall
+#endif
+ [!B1]	ADDKPC	.S2	ret_from_syscall_function,B3,4
+
+	;; Get syscall handler addr from sys_call_table:
+	MVKL	.S2	sys_call_table,B1
+	MVKH	.S2	sys_call_table,B1
+	LDW	.D2T2	*+B1[B0],B0		; B0 = _sys_call_table[__NR_*]
+ ||	LDW	.D1T1	*+A12(THREAD_INFO_FLAGS),A2
+	NOP	4
+	AND	.D1	_TIF_SYSCALL_TRACE,A2,A2 ; check for TIF_SYSCALL_TRACE flag
+ [A2]	BNOP	.S1	tracesys_on,5		 ; call syscall_trace_entry before syscall function
+
+	;; Branch to the corresponding syscall
+	B	.S2	B0
+	ADDKPC	.S2	ret_from_syscall_function,B3,4
+
+ret_from_syscall_function:
+	STW	.D2T1	A4,*+SP(REGS_A4+8)	; save return value in A4
+						; original A4 is in orig_A4
+syscall_exit:
+	;; make sure we don't miss an interrupt setting need_resched or
+	;; sigpending between sampling and the rti
+	MASK_INT B2
+	LDW	.D1T1	*+A12(THREAD_INFO_FLAGS),A2
+	MVK	.S1	_TIF_ALLWORK_MASK,A1
+	NOP	3
+	AND	.D1	A1,A2,A2 ; check for work to do
+ [A2]	BNOP	.S1	syscall_exit_work,5
+
+restore_all:
+	RESTORE_ALL_EXCEPT
+
+	;;
+	;; After a fork we jump here directly from resume,
+	;; so that A4 contains the previous task structure.
+	;;
+	.global	ret_from_fork
+ret_from_fork:
+#ifdef CONFIG_BIG_KERNEL
+	MVKL	.S1	schedule_tail,A0
+	MVKH	.S1	schedule_tail,A0
+	B	.S2X	A0
+#else
+	B	.S2	schedule_tail
+#endif
+	ADDKPC	.S2	ret_from_fork_2,B3,4
+ret_from_fork_2:
+	;; return 0 in A4 for child process
+	GET_THREAD_INFO A12
+	BNOP	.S2	syscall_exit,3
+	MVK	.L2	0,B0
+	STW	.D2T2	B0,*+SP(REGS_A4+8)
+
+	;;
+	;; These are the interrupt handlers, responsible for calling __do_IRQ()
+	;; int6 is used for syscalls (see _system_call entry)
+	;;
+_int4_handler:
+	SAVE_ALL_INT
+	MASK_SYSCALL
+	CALL_INT 4
+
+_int5_handler:
+	SAVE_ALL_INT
+	MASK_SYSCALL
+	CALL_INT 5
+
+_int6_handler:
+	SAVE_ALL_INT
+	MASK_SYSCALL
+	CALL_INT 6
+
+_int7_handler:
+	SAVE_ALL_INT
+	MASK_SYSCALL
+	CALL_INT 7
+
+_int8_handler:
+	SAVE_ALL_INT
+	MASK_SYSCALL
+	CALL_INT 8
+
+_int9_handler:
+	SAVE_ALL_INT
+	MASK_SYSCALL
+	CALL_INT 9
+
+_int10_handler:
+	SAVE_ALL_INT
+	MASK_SYSCALL
+	CALL_INT 10
+
+_int11_handler:
+	SAVE_ALL_INT
+	MASK_SYSCALL
+	CALL_INT 11
+
+_int12_handler:
+	SAVE_ALL_INT
+	MASK_SYSCALL
+	CALL_INT 12
+
+_int13_handler:
+	SAVE_ALL_INT
+	MASK_SYSCALL
+	CALL_INT 13
+
+_int14_handler:
+	SAVE_ALL_INT
+	MASK_SYSCALL
+	CALL_INT 14
+
+_int15_handler:
+	SAVE_ALL_INT
+	MASK_SYSCALL
+	CALL_INT 15
+
+	;;
+	;; Handler for uninitialized and spurious interrupts
+	;;
+	.global _bad_interrupt
+_bad_interrupt:
+	B	.S2	IRP
+	NOP	5
+
+	;;
+	;; Handler for NMI (C6x) and exceptions (C64x+)
+	;;
+	.global _nmi_handler
+_nmi_handler:
+	SAVE_ALL_EXCEPT
+
+	MVC	.S2	EFR,B2
+	CMPEQ	.L2	1,B2,B2
+ ||	MVC	.S2	TSR,B1
+	CLR	.S2	B1,10,10,B1
+	MVC	.S2	B1,TSR
+#ifdef CONFIG_BIG_KERNEL
+ [!B2]	MVKL	.S1	process_exception,A0
+ [!B2]	MVKH	.S1	process_exception,A0
+ [!B2]	B	.S2X	A0
+#else
+ [!B2]	B	.S2	process_exception
+#endif
+ [B2]	B	.S2	system_call_saved
+ [!B2]	ADDAW	.D2	SP,2,B1
+ [!B2]	MV	.D1X	B1,A4
+	ADDKPC	.S2	ret_from_trap,B3,2
+
+ret_from_trap:
+	MV	.D2X	A4,B0
+ [!B0]	BNOP	.S2	ret_from_exception,5
+
+#ifdef CONFIG_BIG_KERNEL
+	MVKL	.S2	system_call_saved_noack,B3
+	MVKH	.S2	system_call_saved_noack,B3
+#endif
+
+	LDW	.D2T2	*+SP(REGS_B0+8),B0
+	LDW	.D2T1	*+SP(REGS_A4+8),A4
+	LDW	.D2T2	*+SP(REGS_B4+8),B4
+	LDW	.D2T1	*+SP(REGS_A6+8),A6
+	LDW	.D2T2	*+SP(REGS_B6+8),B6
+	LDW	.D2T1	*+SP(REGS_A8+8),A8
+#ifdef CONFIG_BIG_KERNEL
+ ||	B	.S2	B3
+#else
+ ||	B	.S2	system_call_saved_noack
+#endif
+	LDW	.D2T2	*+SP(REGS_B8+8),B8
+	NOP	4
+
+	;;
+	;; Jump to schedule() then return to ret_from_isr
+	;;
+#ifdef	CONFIG_PREEMPT
+irq_reschedule:
+#ifdef CONFIG_BIG_KERNEL
+	MVKL	.S1	schedule,A0
+	MVKH	.S1	schedule,A0
+	B	.S2X	A0
+#else
+	B	.S2	schedule
+#endif
+	ADDKPC	.S2	ret_from_interrupt,B3,4
+
+resume_kernel:
+	GET_THREAD_INFO A12
+	LDW	.D1T1	*+A12(THREAD_INFO_PREEMPT_COUNT),A1
+	NOP	4
+ [A1]	BNOP	.S2	restore_all,5
+
+preempt_schedule:
+	GET_THREAD_INFO A2
+	LDW	.D1T1	*+A2(THREAD_INFO_FLAGS),A1
+#ifdef CONFIG_BIG_KERNEL
+	MVKL	.S2	preempt_schedule_irq,B0
+	MVKH	.S2	preempt_schedule_irq,B0
+	NOP	2
+#else
+	NOP	4
+#endif
+	AND	.D1	_TIF_NEED_RESCHED,A1,A1	; check for TIF_NEED_RESCHED flag
+ [!A1]	BNOP	.S2	restore_all,5
+#ifdef CONFIG_BIG_KERNEL
+	B	.S2	B0
+#else
+	B	.S2	preempt_schedule_irq
+#endif
+	ADDKPC	.S2	preempt_schedule,B3,4
+#endif
+
+	.global enable_exception
+enable_exception:
+	DINT
+	MVC	.S2	TSR,B0
+	MVC	.S2	B3,NRP
+	MVK	.L2	0xc,B1
+	OR	.D2	B0,B1,B0
+	MVC	.S2	B0,TSR			;  Set GEE and XEN in TSR
+	B	.S2	NRP
+	NOP	5
+
+	.global sys_sigaltstack
+sys_sigaltstack:
+#ifdef CONFIG_BIG_KERNEL
+	MVKL	.S1	do_sigaltstack,A0	; branch to do_sigaltstack
+	MVKH	.S1	do_sigaltstack,A0
+	B	.S2X	A0
+#else
+	B	.S2	do_sigaltstack
+#endif
+	LDW	.D2T1	*+SP(REGS_SP+8),A6
+	NOP	4
+
+	;; kernel_execve
+	.global kernel_execve
+kernel_execve:
+	MVK	.S2	__NR_execve,B0
+	SWE
+	BNOP	.S2	B3,5
+
+	;;
+	;; Special system calls
+	;; return address is in B3
+	;;
+	.global sys_clone
+sys_clone:
+	ADD	.D1X	SP,8,A4
+#ifdef CONFIG_BIG_KERNEL
+ ||	MVKL	.S1	c6x_clone,A0
+	MVKH	.S1	c6x_clone,A0
+	BNOP	.S2X	A0,5
+#else
+ ||	B	.S2	c6x_clone
+	NOP	5
+#endif
+
+	.global sys_vfork
+sys_vfork:
+	ADD	.D1X	SP,8,A4
+#ifdef CONFIG_BIG_KERNEL
+ ||	MVKL	.S1	c6x_vfork,A0		; branch to _c6x_vfork(struct pt_regs *regs)
+	MVKH	.S1	c6x_vfork,A0
+	BNOP	.S2X	A0,5
+#else
+ ||	B	.S2	c6x_vfork
+	NOP	5
+#endif
+
+	.global sys_rt_sigreturn
+sys_rt_sigreturn:
+	ADD	.D1X	SP,8,A4
+#ifdef CONFIG_BIG_KERNEL
+ ||	MVKL	.S1	do_rt_sigreturn,A0	; branch to _do_rt_sigreturn
+	MVKH	.S1	do_rt_sigreturn,A0
+	BNOP	.S2X	A0,5
+#else
+ ||	B	.S2	do_rt_sigreturn
+	NOP	5
+#endif
+
+	.global sys_execve
+sys_execve:
+	ADDAW	.D2	SP,2,B6			; put regs addr in 4th parameter
+						; & adjust regs stack addr
+	LDW	.D2T2	*+SP(REGS_B4+8),B4
+
+	;; c6x_execve(char *name, char **argv, char **envp, struct pt_regs *regs)
+#ifdef CONFIG_BIG_KERNEL
+ ||	MVKL	.S1	c6x_execve,A0
+	MVKH	.S1	c6x_execve,A0
+	B	.S2X	A0
+#else
+ ||	B	.S2	c6x_execve
+#endif
+	STW	.D2T2	B3,*SP--[2]
+	ADDKPC	.S2	ret_from_c6x_execve,B3,3
+
+ret_from_c6x_execve:
+	LDW	.D2T2	*++SP[2],B3
+	NOP	4
+	BNOP	.S2	B3,5
+
+	.global sys_pread_c6x
+sys_pread_c6x:
+	MV	.D2X	A8,B7
+#ifdef CONFIG_BIG_KERNEL
+ ||	MVKL	.S1	sys_pread64,A0
+	MVKH	.S1	sys_pread64,A0
+	BNOP	.S2X	A0,5
+#else
+ ||	B	.S2	sys_pread64
+	NOP	5
+#endif
+
+	.global sys_pwrite_c6x
+sys_pwrite_c6x:
+	MV	.D2X	A8,B7
+#ifdef CONFIG_BIG_KERNEL
+ ||	MVKL	.S1	sys_pwrite64,A0
+	MVKH	.S1	sys_pwrite64,A0
+	BNOP	.S2X	A0,5
+#else
+ ||	B	.S2	sys_pwrite64
+	NOP	5
+#endif
+
+	.global sys_truncate64_c6x
+sys_truncate64_c6x:
+	MV	.D2X	A6,B5
+#ifdef CONFIG_BIG_KERNEL
+ ||	MVKL	.S1	sys_truncate64,A0
+	MVKH	.S1	sys_truncate64,A0
+	BNOP	.S2X	A0,5
+#else
+ ||	B	.S2	sys_truncate64
+	NOP	5
+#endif
+
+	.global sys_ftruncate64_c6x
+sys_ftruncate64_c6x:
+	MV	.D2X	A6,B5
+#ifdef CONFIG_BIG_KERNEL
+ ||	MVKL	.S1	sys_ftruncate64,A0
+	MVKH	.S1	sys_ftruncate64,A0
+	BNOP	.S2X	A0,5
+#else
+ ||	B	.S2	sys_ftruncate64
+	NOP	5
+#endif
+
+#ifdef __ARCH_WANT_SYSCALL_OFF_T
+;; On Entry
+;;   A4 - fd
+;;   B4 - offset_lo (LE), offset_hi (BE)
+;;   A6 - offset_lo (BE), offset_hi (LE)
+;;   B6 - len
+;;   A8 - advice
+	.global sys_fadvise64_c6x
+sys_fadvise64_c6x:
+#ifdef CONFIG_BIG_KERNEL
+	MVKL	.S1	sys_fadvise64,A0
+	MVKH	.S1	sys_fadvise64,A0
+	BNOP	.S2X	A0,2
+#else
+	B	.S2	sys_fadvise64
+	NOP	2
+#endif
+#ifdef CONFIG_CPU_BIG_ENDIAN
+	MV	.L2	B4,B5
+ ||	MV	.D2X	A6,B4
+#else
+	MV	.D2X	A6,B5
+#endif
+	MV	.D1X	B6,A6
+	MV	.D2X	A8,B6
+#endif
+
+;; On Entry
+;;   A4 - fd
+;;   B4 - offset_lo (LE), offset_hi (BE)
+;;   A6 - offset_lo (BE), offset_hi (LE)
+;;   B6 - len_lo (LE), len_hi (BE)
+;;   A8 - len_lo (BE), len_hi (LE)
+;;   B8 - advice
+	.global sys_fadvise64_64_c6x
+sys_fadvise64_64_c6x:
+#ifdef CONFIG_BIG_KERNEL
+	MVKL	.S1	sys_fadvise64_64,A0
+	MVKH	.S1	sys_fadvise64_64,A0
+	BNOP	.S2X	A0,2
+#else
+	B	.S2	sys_fadvise64_64
+	NOP	2
+#endif
+#ifdef CONFIG_CPU_BIG_ENDIAN
+	MV	.L2	B4,B5
+ ||	MV	.D2X	A6,B4
+	MV	.L1	A8,A6
+ ||	MV	.D1X	B6,A7
+#else
+	MV	.D2X	A6,B5
+	MV	.L1	A8,A7
+ ||	MV	.D1X	B6,A6
+#endif
+	MV	.L2	B8,B6
+
+;; On Entry
+;;   A4 - fd
+;;   B4 - mode
+;;   A6 - offset_hi
+;;   B6 - offset_lo
+;;   A8 - len_hi
+;;   B8 - len_lo
+	.global sys_fallocate_c6x
+sys_fallocate_c6x:
+#ifdef CONFIG_BIG_KERNEL
+	MVKL	.S1	sys_fallocate,A0
+	MVKH	.S1	sys_fallocate,A0
+	BNOP	.S2X	A0,1
+#else
+	B	.S2	sys_fallocate
+	NOP
+#endif
+	MV	.D1	A6,A7
+	MV	.D1X	B6,A6
+	MV	.D2X	A8,B7
+	MV	.D2	B8,B6
diff --git a/arch/c6x/kernel/head.S b/arch/c6x/kernel/head.S
new file mode 100644
index 0000000..af1934c
--- /dev/null
+++ b/arch/c6x/kernel/head.S
@@ -0,0 +1,127 @@
+;
+;  linux/arch/c6x/kernel/head.s
+;
+;  Port on Texas Instruments TMS320C6x architecture
+;
+;  Copyright (C) 2004, 2009, 2010, 2011 Texas Instruments Incorporated
+;  Author: Aurelien Jacquiot (aurelien.jacquiot@...una.com)
+;
+;  This program is free software; you can redistribute it and/or modify
+;  it under the terms of the GNU General Public License version 2 as
+;  published by the Free Software Foundation.
+;
+
+#include "tags.h"
+
+	.global	_c_int00
+_c_int00:
+	;; Save tag magic and pointer
+	MV	.S1	A4,A10
+	MV	.S2	B4,B10
+
+#ifdef CONFIG_XIP_KERNEL
+	;; Setup a temporary stack to use when calling C code to
+	;; relocate XIP data.
+	MVKL	.S2	_end,B15
+	MVKH	.S2	_end,B15
+	ADDAW	.D2     B15,4096,B15
+	AND	.D2	~7,B15,B15
+#ifdef CONFIG_BIG_KERNEL
+	MVKL	.S2	c6x_relocate_xip_data,B0
+	MVKH	.S2	c6x_relocate_xip_data,B0
+	B	.S2	B0
+	ADDKPC	.S2	_ret_from_reloc,B3,4
+_ret_from_reloc:
+#else
+	CALLP   .S2	c6x_relocate_xip_data,B3
+#endif
+#else
+	;; Set the stack pointer
+	MVKL	.S2	current_ksp,B0
+	MVKH	.S2	current_ksp,B0
+	LDW	.D2T2	*B0,B15
+	NOP	4
+	AND	.D2	~7,B15,B15
+#endif
+
+#ifdef CONFIG_MTD_UCLINUX
+#ifdef CONFIG_BIG_KERNEL
+	MVKL	.S2	c6x_mtd_early_init,B0
+	MVKH	.S2	c6x_mtd_early_init,B0
+	B	.S2	B0
+	ADDKPC	.S2	_ret_from_mtd_early_init,B3,4
+_ret_from_mtd_early_init:
+#else
+	CALLP	.S2	c6x_mtd_early_init,B3
+#endif
+#endif
+
+	;; Set global page pointer in B14
+	MVKL	.S2	__bss_start,B14
+	MVKH	.S2	__bss_start,B14
+
+	;; Clear bss area
+	MVKL	.S1	__bss_start,A4
+	MVKH	.S1	__bss_start,A4
+	MVKL	.S1	__bss_stop,A6
+	MVKH	.S1	__bss_stop,A6
+
+	CMPLTU	.L1	A4,A6,A1
+ [!A1]	B	.S1	__bss_done
+	ZERO	.L2	B4
+	SUB	.L1	A6,A4,A5
+	SHR	.S1	A5,2,A3
+	NOP	2
+
+	SUB	.L2X	A3,1,B0
+  ||	MV	.L1X	B4,A3
+
+__bss_loop:
+	STW	.D1T1	A3,*A4++
+|| [B0]	BNOP	.S1	__bss_loop,5
+|| [B0]	SUB	.L2	B0,1,B0
+
+__bss_done:
+
+	;; Clear GIE and PGIE
+	MVC	.S2	CSR,B2
+	CLR	.S2	B2,0,1,B2
+	MVC	.S2	B2,CSR
+	MVC	.S2	TSR,B2
+	CLR	.S2	B2,0,1,B2
+	MVC	.S2	B2,TSR
+	MVC	.S2	ITSR,B2
+	CLR	.S2	B2,0,1,B2
+	MVC	.S2	B2,ITSR
+	MVC	.S2	NTSR,B2
+	CLR	.S2	B2,0,1,B2
+	MVC	.S2	B2,NTSR
+
+#ifdef CONFIG_XIP_KERNEL
+	;; Set the stack pointer
+	MVKL	.S2	current_ksp,B0
+	MVKH	.S2	current_ksp,B0
+	LDW	.D2T2	*B0,B15
+	NOP	4
+	AND	.D2	~7,B15,B15
+#endif
+
+	MVKL	.S2	TAGS_MAGIC,B0
+	MVKH	.S2	TAGS_MAGIC,B0
+	CMPEQ	.L1	A10,A0,A0
+	MVKL	.S2	c6x_tags_pointer,B1
+	MVKH	.S2	c6x_tags_pointer,B1
+  [!A0] MVK	.S2	0,B10
+	STW	.D2T2	B10,*B1
+
+	;; Jump to Linux init
+#ifdef CONFIG_BIG_KERNEL
+	MVKL	.S1	start_kernel,A0
+	MVKH	.S1	start_kernel,A0
+	B	.S2X	A0
+#else
+	B	.S2	start_kernel
+#endif
+	NOP	5
+L1:	BNOP	.S2	L1,5
+
diff --git a/arch/c6x/kernel/irq.c b/arch/c6x/kernel/irq.c
new file mode 100644
index 0000000..323d119
--- /dev/null
+++ b/arch/c6x/kernel/irq.c
@@ -0,0 +1,119 @@
+/*
+ *  linux/arch/c6x/kernel/irq.c
+ *
+ *  Port on Texas Instruments TMS320C6x architecture
+ *
+ *  Copyright (C) 2004, 2006, 2009, 2010, 2011 Texas Instruments Incorporated
+ *  Author: Aurelien Jacquiot (aurelien.jacquiot@...una.com)
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ *
+ *  C6x general interrupt handling code.
+ */
+#include <linux/types.h>
+#include <linux/sched.h>
+#include <linux/kernel_stat.h>
+#include <linux/errno.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/hardirq.h>
+#include <linux/seq_file.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/io.h>
+
+#include <asm/system.h>
+#include <asm/irq.h>
+#include <asm/traps.h>
+#include <asm/page.h>
+#include <asm/hardirq.h>
+#include <asm/hardware.h>
+
+DECLARE_PER_CPU(struct kernel_stat, kstat);
+
+unsigned long irq_err_count;
+
+#ifndef hw_to_kernel_irq
+#define hw_to_kernel_irq(hw) (hw)
+#endif
+
+static void mask_core_irq(struct irq_data *data)
+{
+	BUG_ON(data->irq >= NR_SYS_IRQS);
+	and_creg(IER, ~(1 << data->irq));
+}
+
+static void unmask_core_irq(struct irq_data *data)
+{
+	BUG_ON(data->irq >= NR_SYS_IRQS);
+	or_creg(IER, 1 << data->irq);
+}
+
+static struct irq_chip core_irq_chip = {
+	.name		= "C64x+",
+	.irq_mask	= mask_core_irq,
+	.irq_unmask	= unmask_core_irq,
+};
+
+void ack_bad_irq(int irq)
+{
+	printk(KERN_ERR "IRQ: spurious interrupt %d\n", irq);
+	irq_err_count++;
+}
+
+asmlinkage void c6x_do_IRQ(unsigned int prio, struct pt_regs *regs)
+{
+	struct pt_regs *old_regs = set_irq_regs(regs);
+
+	irq_enter();
+
+	BUG_ON(prio >= NR_SYS_IRQS);
+
+	generic_handle_irq(hw_to_kernel_irq(prio));
+
+	irq_exit();
+
+	set_irq_regs(old_regs);
+}
+
+void __init init_IRQ(void)
+{
+	int i;
+
+	/* Mask all general IRQs */
+	and_creg(IER, ~0xfff0);
+
+	for (i = 0; i < NR_SYS_IRQS; i++)
+		irq_set_chip_and_handler(i, &core_irq_chip, handle_level_irq);
+
+#ifdef CONFIG_PIC_C64XPLUS
+	init_pic_c64xplus();
+#endif
+
+	/* Clear all general IRQ flags */
+	set_creg(ICR, 0xfff0);
+}
+
+/* This is only necessary to squelch some warning about
+ * IRQs being enabled early. radix_tree_init() leaves
+ * interrupts enabled during early boot when they should
+ * be disabled. None of the individual bits in IER are
+ * enabled so we don't actually get interrupts, just the
+ * warning from init/main.c boot code.
+ */
+int __init __weak arch_early_irq_init(void)
+{
+	/* clear interrupt flags */
+	set_creg(ICR, 0xfff0);
+	local_irq_disable();
+	return 0;
+}
+
+int arch_show_interrupts(struct seq_file *p, int prec)
+{
+	seq_printf(p, "%*s: %10lu\n", prec, "Err", irq_err_count);
+	return 0;
+}
+
diff --git a/arch/c6x/kernel/module.c b/arch/c6x/kernel/module.c
new file mode 100644
index 0000000..8356f99
--- /dev/null
+++ b/arch/c6x/kernel/module.c
@@ -0,0 +1,249 @@
+/*
+ *  linux/arch/c6x/kernel/module.c
+ *
+ *  Port on Texas Instruments TMS320C6x architecture
+ *
+ *  Copyright (C) 2005, 2009, 2010, 2011 Texas Instruments Incorporated
+ *  Author: Thomas Charleux (thomas.charleux@...una.com)
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ *
+ *  This file handles the architecture-dependent parts of process handling.
+ */
+#include <linux/moduleloader.h>
+#include <linux/elf.h>
+#include <linux/vmalloc.h>
+#include <linux/slab.h>
+#include <linux/fs.h>
+#include <linux/string.h>
+#include <linux/kernel.h>
+#include <linux/bug.h>
+#include <asm/byteorder.h>
+
+#if 0
+#define DEBUGP(fmt...) printk(KERN_INFO fmt)
+#else
+#define DEBUGP(fmt...)
+#endif
+
+void *module_alloc(unsigned long size)
+{
+	if (size == 0)
+		return NULL;
+	return vmalloc_exec(size);
+}
+
+
+/* Free memory returned from module_alloc */
+void module_free(struct module *mod, void *module_region)
+{
+	vfree(module_region);
+	/* FIXME: If module_region == mod->init_region, trim exception
+	   table entries. */
+}
+
+/*
+ * finish loading the module
+ */
+int module_finalize(const Elf_Ehdr *hdr,
+		    const Elf_Shdr *sechdrs,
+		    struct module *me)
+{
+	return 0;
+}
+
+/*
+ * finish clearing the module
+ */
+void module_arch_cleanup(struct module *mod)
+{
+	module_bug_cleanup(mod);
+}
+
+
+/* We don't need anything special. */
+int module_frob_arch_sections(Elf_Ehdr *hdr,
+			      Elf_Shdr *sechdrs,
+			      char *secstrings,
+			      struct module *mod)
+{
+	return 0;
+}
+
+static inline int fixup_pcr(u32 *ip, Elf32_Addr dest, u32 maskbits, int shift)
+{
+	u32 opcode;
+	long ep = (long)ip & ~31;
+	long delta = ((long)dest - ep) >> 2;
+	long mask = (1 << maskbits) - 1;
+
+	if ((delta >> (maskbits - 1)) == 0 ||
+	    (delta >> (maskbits - 1)) == -1) {
+		opcode = *ip;
+		opcode &= ~(mask << shift);
+		opcode |= ((delta & mask) << shift);
+		*ip = opcode;
+
+		DEBUGP("REL PCR_S%d[%p] dest[0p] opcode[%08x]\n",
+		       maskbits, ip, (void *)dest, opcode);
+
+		return 0;
+	}
+	printk(KERN_ERR "PCR_S%d reloc %p -> %p out of range!\n",
+	       maskbits, ip, (void *)dest);
+
+	return -1;
+}
+
+/*
+ * apply a REL relocation
+ */
+int apply_relocate(Elf32_Shdr *sechdrs,
+		   const char *strtab,
+		   unsigned int symindex,
+		   unsigned int relsec,
+		   struct module *me)
+{
+	Elf32_Rel *rel = (void *) sechdrs[relsec].sh_addr;
+	Elf_Sym *sym;
+	u32 *location;
+	unsigned int i;
+	Elf32_Addr v;
+	Elf_Addr offset = 0;
+
+	DEBUGP("Applying relocate section %u to %u with offset[0x%x]\n", relsec,
+	       sechdrs[relsec].sh_info, offset);
+
+	for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) {
+		/* This is where to make the change */
+		location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr
+			+ rel[i].r_offset - offset;
+
+		/* This is the symbol it is referring to.  Note that all
+		   undefined symbols have been resolved.  */
+		sym = (Elf_Sym *)sechdrs[symindex].sh_addr
+			+ ELF32_R_SYM(rel[i].r_info);
+
+		/* this is the adjustment to be made */
+		v = sym->st_value;
+
+		switch (ELF32_R_TYPE(rel[i].r_info)) {
+		case R_C6000_ABS32:
+			DEBUGP("REL ABS32: [%p] = 0x%x\n", location, v);
+			*location = v;
+			break;
+		case R_C6000_ABS16:
+			DEBUGP("REL ABS16: [%p] = 0x%x\n", location, v);
+			*(u16 *)location = v;
+			break;
+		case R_C6000_ABS8:
+			DEBUGP("REL ABS8: [%p] = 0x%x\n", location, v);
+			*(u8 *)location = v;
+			break;
+		case R_C6000_PCR_S21:
+			if (fixup_pcr(location, v, 21, 7))
+				return -ENOEXEC;
+			break;
+		case R_C6000_PCR_S12:
+			if (fixup_pcr(location, v, 12, 16))
+				return -ENOEXEC;
+			break;
+		case R_C6000_PCR_S10:
+			if (fixup_pcr(location, v, 10, 13))
+				return -ENOEXEC;
+			break;
+		default:
+			printk(KERN_ERR "module %s: Unknown REL relocation: %u\n",
+			       me->name, ELF32_R_TYPE(rel[i].r_info));
+			return -ENOEXEC;
+		}
+	}
+
+	return 0;
+}
+
+/*
+ * apply a RELA relocation
+ */
+int apply_relocate_add(Elf32_Shdr *sechdrs,
+		       const char *strtab,
+		       unsigned int symindex,
+		       unsigned int relsec,
+		       struct module *me)
+{
+	Elf32_Rela *rel = (void *) sechdrs[relsec].sh_addr;
+	Elf_Sym *sym;
+	u32 *location, opcode;
+	unsigned int i;
+	Elf32_Addr v;
+	Elf_Addr offset = 0;
+
+	DEBUGP("Applying relocate section %u to %u with offset 0x%x\n", relsec,
+	       sechdrs[relsec].sh_info, offset);
+
+	for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) {
+		/* This is where to make the change */
+		location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr
+			+ rel[i].r_offset - offset;
+
+		/* This is the symbol it is referring to.  Note that all
+		   undefined symbols have been resolved.  */
+		sym = (Elf_Sym *)sechdrs[symindex].sh_addr
+			+ ELF32_R_SYM(rel[i].r_info);
+
+		/* this is the adjustment to be made */
+		v = sym->st_value + rel[i].r_addend;
+
+		switch (ELF32_R_TYPE(rel[i].r_info)) {
+		case R_C6000_ABS32:
+			DEBUGP("RELA ABS32: [%p] = 0x%x\n", location, v);
+			*location = v;
+			break;
+		case R_C6000_ABS16:
+			DEBUGP("RELA ABS16: [%p] = 0x%x\n", location, v);
+			*(u16 *)location = v;
+			break;
+		case R_C6000_ABS8:
+			DEBUGP("RELA ABS8: [%p] = 0x%x\n", location, v);
+			*(u8 *)location = v;
+			break;
+		case R_C6000_ABS_L16:
+			opcode = *location;
+			opcode &= ~0x7fff80;
+			opcode |= ((v & 0xffff) << 7);
+			DEBUGP("RELA ABS_L16[%p] v[0x%x] opcode[0x%x]\n",
+			       location, v, opcode);
+			*location = opcode;
+			break;
+		case R_C6000_ABS_H16:
+			opcode = *location;
+			opcode &= ~0x7fff80;
+			opcode |= ((v >> 9) & 0x7fff80);
+			DEBUGP("RELA ABS_H16[%p] v[0x%x] opcode[0x%x]\n",
+			       location, v, opcode);
+			*location = opcode;
+			break;
+		case R_C6000_PCR_S21:
+			if (fixup_pcr(location, v, 21, 7))
+				return -ENOEXEC;
+			break;
+		case R_C6000_PCR_S12:
+			if (fixup_pcr(location, v, 12, 16))
+				return -ENOEXEC;
+			break;
+		case R_C6000_PCR_S10:
+			if (fixup_pcr(location, v, 10, 13))
+				return -ENOEXEC;
+			break;
+		default:
+			printk(KERN_ERR "module %s: Unknown RELA relocation: %u\n",
+			       me->name, ELF32_R_TYPE(rel[i].r_info));
+			return -ENOEXEC;
+		}
+	}
+
+	return 0;
+}
+
diff --git a/arch/c6x/kernel/process.c b/arch/c6x/kernel/process.c
new file mode 100644
index 0000000..3aea8b8
--- /dev/null
+++ b/arch/c6x/kernel/process.c
@@ -0,0 +1,349 @@
+/*
+ *  linux/arch/c6x/kernel/process.c
+ *
+ *  Port on Texas Instruments TMS320C6x architecture
+ *
+ *  Copyright (C) 2004, 2006, 2009, 2010, 2011 Texas Instruments Incorporated
+ *  Author: Aurelien Jacquiot (aurelien.jacquiot@...una.com)
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ *
+ *  This file handles the architecture-dependent parts of process handling.
+ */
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/smp.h>
+#include <linux/stddef.h>
+#include <linux/unistd.h>
+#include <linux/ptrace.h>
+#include <linux/slab.h>
+#include <linux/user.h>
+#include <linux/reboot.h>
+#include <linux/init_task.h>
+#include <linux/mqueue.h>
+#include <linux/stddef.h>
+#include <linux/module.h>
+#include <linux/tick.h>
+#include <linux/sched.h>
+
+#include <asm/uaccess.h>
+#include <asm/system.h>
+#include <asm/traps.h>
+#include <asm/setup.h>
+#include <asm/pgtable.h>
+#include <asm/pm.h>
+#include <asm/string.h>
+#include <asm/syscalls.h>
+
+#include <mach/board.h>  /* for c6x_arch_idle_led() */
+
+static struct signal_struct init_signals = INIT_SIGNALS(init_signals);
+static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand);
+/*
+ * Initial thread structure.
+ *
+ * We need to make sure that this is THREAD_SIZE aligned due to the
+ * way process stacks are handled. This is done by having a special
+ * "init_task" linker map entry..
+ */
+union thread_union init_thread_union __init_task_data =	{
+	INIT_THREAD_INFO(init_task)
+};
+
+/*
+ * Initial task structure.
+ *
+ * All other task structs will be allocated on slabs in fork.c
+ */
+struct task_struct init_task = INIT_TASK(init_task);
+EXPORT_SYMBOL(init_task);
+
+extern asmlinkage void ret_from_fork(void);
+
+/*
+ * power off function, if any
+ */
+void (*pm_power_off)(void);
+EXPORT_SYMBOL(pm_power_off);
+
+/*
+ * power management idle function, if any..
+ */
+void (*pm_idle)(void);
+EXPORT_SYMBOL(pm_idle);
+
+static void default_idle(void)
+{
+#if defined(CONFIG_PM)
+	pwrd_set(PWRD_PD1A);
+#endif
+#ifndef CONFIG_ARCH_SIM
+	do_idle(); /* do nothing until interrupt */
+#endif
+}
+
+/*
+ * The idle loop for C64x
+ */
+void cpu_idle(void)
+{
+	/* endless idle loop with no priority at all */
+	while (1) {
+#ifdef CONFIG_TICK_ONESHOT
+		tick_nohz_stop_sched_tick(1);
+#endif
+		while (!need_resched()) {
+			void (*idle)(void);
+
+			smp_rmb();
+			idle = pm_idle;
+			if (!idle)
+				idle = default_idle;
+			idle();
+		}
+#ifdef CONFIG_TICK_ONESHOT
+		tick_nohz_restart_sched_tick();
+#endif
+		preempt_enable_no_resched();
+		schedule();
+		preempt_disable();
+	}
+}
+
+void machine_restart(char *__unused)
+{
+	while (1)
+		;
+}
+
+void machine_halt(void)
+{
+	while (1)
+		;
+}
+
+void machine_power_off(void)
+{
+	while (1)
+		;
+}
+
+void show_regs(struct pt_regs *regs)
+{
+	printk(KERN_INFO "\n");
+	printk(KERN_INFO "PC: %08lx SP: %08lx\n",
+	       regs->pc, regs->sp);
+	printk(KERN_INFO "Status: %08lx ORIG_A4: %08lx\n",
+	       regs->csr, regs->orig_a4);
+	printk(KERN_INFO "A0: %08lx  B0: %08lx\n",
+	       regs->a0, regs->b0);
+	printk(KERN_INFO "A1: %08lx  B1: %08lx\n",
+	       regs->a1, regs->b1);
+	printk(KERN_INFO "A2: %08lx  B2: %08lx\n",
+	       regs->a2, regs->b2);
+	printk(KERN_INFO "A3: %08lx  B3: %08lx\n",
+	       regs->a3, regs->b3);
+	printk(KERN_INFO "A4: %08lx  B4: %08lx\n",
+	       regs->a4, regs->b4);
+	printk(KERN_INFO "A5: %08lx  B5: %08lx\n",
+	       regs->a5, regs->b5);
+	printk(KERN_INFO "A6: %08lx  B6: %08lx\n",
+	       regs->a6, regs->b6);
+	printk(KERN_INFO "A7: %08lx  B7: %08lx\n",
+	       regs->a7, regs->b7);
+	printk(KERN_INFO "A8: %08lx  B8: %08lx\n",
+	       regs->a8, regs->b8);
+	printk(KERN_INFO "A9: %08lx  B9: %08lx\n",
+	       regs->a9, regs->b9);
+	printk(KERN_INFO "A10: %08lx  B10: %08lx\n",
+	       regs->a10, regs->b10);
+	printk(KERN_INFO "A11: %08lx  B11: %08lx\n",
+	       regs->a11, regs->b11);
+	printk(KERN_INFO "A12: %08lx  B12: %08lx\n",
+	       regs->a12, regs->b12);
+	printk(KERN_INFO "A13: %08lx  B13: %08lx\n",
+	       regs->a13, regs->b13);
+	printk(KERN_INFO "A14: %08lx  B14: %08lx\n",
+	       regs->a14, regs->dp);
+	printk(KERN_INFO "A15: %08lx  B15: %08lx\n",
+	       regs->a15, regs->sp);
+	printk(KERN_INFO "A16: %08lx  B16: %08lx\n",
+	       regs->a16, regs->b16);
+	printk(KERN_INFO "A17: %08lx  B17: %08lx\n",
+	       regs->a17, regs->b17);
+	printk(KERN_INFO "A18: %08lx  B18: %08lx\n",
+	       regs->a18, regs->b18);
+	printk(KERN_INFO "A19: %08lx  B19: %08lx\n",
+	       regs->a19, regs->b19);
+	printk(KERN_INFO "A20: %08lx  B20: %08lx\n",
+	       regs->a20, regs->b20);
+	printk(KERN_INFO "A21: %08lx  B21: %08lx\n",
+	       regs->a21, regs->b21);
+	printk(KERN_INFO "A22: %08lx  B22: %08lx\n",
+	       regs->a22, regs->b22);
+	printk(KERN_INFO "A23: %08lx  B23: %08lx\n",
+	       regs->a23, regs->b23);
+	printk(KERN_INFO "A24: %08lx  B24: %08lx\n",
+	       regs->a24, regs->b24);
+	printk(KERN_INFO "A25: %08lx  B25: %08lx\n",
+	       regs->a25, regs->b25);
+	printk(KERN_INFO "A26: %08lx  B26: %08lx\n",
+	       regs->a26, regs->b26);
+	printk(KERN_INFO "A27: %08lx  B27: %08lx\n",
+	       regs->a27, regs->b27);
+	printk(KERN_INFO "A28: %08lx  B28: %08lx\n",
+	       regs->a28, regs->b28);
+	printk(KERN_INFO "A29: %08lx  B29: %08lx\n",
+	       regs->a29, regs->b29);
+	printk(KERN_INFO "A30: %08lx  B30: %08lx\n",
+	       regs->a30, regs->b30);
+	printk(KERN_INFO "A31: %08lx  B31: %08lx\n",
+	       regs->a31, regs->b31);
+}
+
+
+static void kernel_thread_helper(int dummy, void *arg, int (*fn)(void *))
+{
+	do_exit(fn(arg));
+}
+
+/*
+ * Create a kernel thread
+ */
+int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
+{
+	struct pt_regs regs;
+
+	/*
+	 * copy_thread sets a4 to zero (child return from fork)
+	 * so we can't just set things up to directly return to
+	 * fn.
+	 */
+	memset(&regs, 0, sizeof(regs));
+	regs.b4 = (unsigned long) arg;
+	regs.a6 = (unsigned long) fn;
+	regs.pc = (unsigned long) kernel_thread_helper;
+	local_save_flags(regs.csr);
+	regs.csr |= 1;
+	regs.tsr = 5; /* Set GEE and GIE in TSR */
+
+	/* Ok, create the new process.. */
+	return do_fork(flags | CLONE_VM | CLONE_UNTRACED, -1, &regs, 0, NULL, NULL);
+}
+EXPORT_SYMBOL(kernel_thread);
+
+void flush_thread(void)
+{
+}
+
+void exit_thread(void)
+{
+}
+
+/*
+ * vfork syscall is deprecated but uClibc tests for _NR_vfork as a check
+ * for __libc_vfork() existence. So we provide the syscall even though
+ * __libc_vfork() actually uses the clone syscall.
+ */
+asmlinkage int c6x_vfork(struct pt_regs *regs)
+{
+	return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs->sp, regs, 0, NULL, NULL);
+}
+
+asmlinkage int c6x_clone(struct pt_regs *regs)
+{
+	unsigned long clone_flags;
+	unsigned long newsp;
+
+	/* syscall puts clone_flags in A4 and usp in B4 */
+	clone_flags = regs->orig_a4;
+	if (regs->b4)
+		newsp = regs->b4;
+	else
+		newsp = regs->sp;
+
+	return do_fork(clone_flags, newsp, regs, 0, (int __user *)regs->a6, (int __user *)regs->b6);
+}
+
+/*
+ * Do necessary setup to start up a newly executed thread.
+ */
+void start_thread(struct pt_regs *regs, unsigned int pc, unsigned long usp)
+{
+	/*
+	 * The binfmt loader will setup a "full" stack, but the C6X
+	 * operates an "empty" stack. So we adjust the usp so that
+	 * argc doesn't get destroyed if an interrupt is taken before
+	 * it is read from the stack.
+	 *
+	 * NB: Library startup code needs to match this.
+	 */
+	usp -= 8;
+
+	set_fs(USER_DS);
+	regs->pc  = pc;
+	regs->sp  = usp;
+	regs->tsr |= 0x40; /* set user mode */
+	current->thread.usp = usp;
+}
+
+/*
+ * Copy a new thread context in its stack.
+ */
+int copy_thread(unsigned long clone_flags, unsigned long usp,
+		unsigned long ustk_size,
+		struct task_struct *p, struct pt_regs *regs)
+{
+	struct pt_regs *childregs;
+
+	childregs = task_pt_regs(p);
+
+	*childregs = *regs;
+	childregs->a4 = 0;
+
+	if (usp == -1)
+		/* case of  __kernel_thread: we return to supervisor space */
+		childregs->sp = (unsigned long)(childregs + 1);
+	else
+		/* Otherwise use the given stack */
+		childregs->sp = usp;
+
+	/* Set usp/ksp */
+	p->thread.usp = childregs->sp;
+	/* switch_to uses stack to save/restore 14 callee-saved regs */
+	thread_saved_ksp(p) = (unsigned long)childregs - 8;
+	p->thread.pc = (unsigned int) ret_from_fork;
+	p->thread.wchan	= (unsigned long) ret_from_fork;
+	return 0;
+}
+
+/*
+ * c6x_execve() executes a new program.
+ */
+asmlinkage long c6x_execve(const char __user *name,
+			   const char __user *const __user *argv,
+			   const char __user *const __user *envp,
+			   struct pt_regs *regs)
+{
+	int error;
+	char *filename;
+
+	filename = getname(name);
+	error = PTR_ERR(filename);
+	if (IS_ERR(filename))
+		goto out;
+
+	error = do_execve(filename, argv, envp, regs);
+	putname(filename);
+out:
+	return error;
+}
+
+unsigned long get_wchan(struct task_struct *p)
+{
+	return p->thread.wchan;
+}
diff --git a/arch/c6x/kernel/ptrace.c b/arch/c6x/kernel/ptrace.c
new file mode 100644
index 0000000..fd38463
--- /dev/null
+++ b/arch/c6x/kernel/ptrace.c
@@ -0,0 +1,284 @@
+/*
+ *  linux/arch/c6x/kernel/ptrace.c
+ *
+ *  Port on Texas Instruments TMS320C6x architecture
+ *
+ *  Copyright (C) 2004, 2006, 2009, 2010, 2011 Texas Instruments Incorporated
+ *  Author: Aurelien Jacquiot (aurelien.jacquiot@...una.com)
+ *
+ *  Updated for 2.6.34: Mark Salter <msalter@...hat.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ */
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/signal.h>
+#include <linux/mm.h>
+#include <linux/errno.h>
+#include <linux/ptrace.h>
+#include <linux/user.h>
+#include <linux/timer.h>
+#include <linux/security.h>
+#include <linux/tracehook.h>
+#include <linux/uaccess.h>
+
+#include <asm/segment.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/pgalloc.h>
+#include <asm/system.h>
+#include <asm/atomic.h>
+#include <asm/cacheflush.h>
+
+/*
+ * does not yet catch signals sent when the child dies.
+ * in exit.c or in signal.c.
+ */
+
+/* Find the stack offset for a register */
+#define PT_REG(reg)	  ((int)&((struct pt_regs *)0)->reg)
+#define PT_REG_SIZE	  (sizeof(struct pt_regs))
+
+#ifdef _BIG_ENDIAN
+#define PT_REGPAIR(odd, even) PT_REG(odd), PT_REG(even)
+#else
+#define PT_REGPAIR(odd, even) PT_REG(even), PT_REG(odd)
+#endif
+
+/* Mapping from PT_xxx to the stack offset at which the register is
+   saved.  Notice that usp has no stack-slot and needs to be treated
+   specially (see get_reg/put_reg below). */
+
+static int regoff[] = {
+	PT_REGPAIR(tsr, orig_a4),
+	PT_REGPAIR(rilc, ilc),
+	PT_REGPAIR(pc, csr),
+
+	PT_REGPAIR(b17, b16),
+	PT_REGPAIR(b19, b18),
+	PT_REGPAIR(b21, b20),
+	PT_REGPAIR(b23, b22),
+	PT_REGPAIR(b25, b24),
+	PT_REGPAIR(b27, b26),
+	PT_REGPAIR(b29, b28),
+	PT_REGPAIR(b31, b30),
+
+	PT_REGPAIR(b1, b0),
+	PT_REGPAIR(b3, b2),
+	PT_REGPAIR(b5, b4),
+	PT_REGPAIR(b7, b6),
+	PT_REGPAIR(b9, b8),
+	PT_REGPAIR(b11, b10),
+	PT_REGPAIR(b13, b12),
+
+	PT_REGPAIR(a17, a16),
+	PT_REGPAIR(a19, a18),
+	PT_REGPAIR(a21, a20),
+	PT_REGPAIR(a23, a22),
+	PT_REGPAIR(a25, a24),
+	PT_REGPAIR(a27, a26),
+	PT_REGPAIR(a29, a28),
+	PT_REGPAIR(a31, a30),
+
+	PT_REGPAIR(a1, a0),
+	PT_REGPAIR(a3, a2),
+	PT_REGPAIR(a5, a4),
+	PT_REGPAIR(a7, a6),
+	PT_REGPAIR(a9, a8),
+	PT_REGPAIR(a11, a10),
+	PT_REGPAIR(a13, a12),
+
+	PT_REGPAIR(a15, a14),
+	PT_REGPAIR(sp, dp),
+};
+
+/*
+ * Get a register number from live pt_regs for the specified task.
+ */
+static inline long get_reg(struct task_struct *task, int regno)
+{
+	unsigned long  *addr;
+	struct pt_regs *regs = task_pt_regs(task);
+
+	if (regno < sizeof(regoff)/sizeof(regoff[0]))
+		addr = (unsigned long *) ((unsigned long) regs + regoff[regno]);
+	else
+		return 0;
+	return *addr;
+}
+
+/*
+ * Write contents of register REGNO in task TASK.
+ */
+static inline int put_reg(struct task_struct *task,
+			  int regno,
+			  unsigned long data)
+{
+	unsigned long *addr;
+	struct pt_regs *regs = task_pt_regs(task);
+
+	if (regno < sizeof(regoff)/sizeof(regoff[0]))
+		addr = (unsigned long *)((unsigned long) regs + regoff[regno]);
+	else
+		return -1;
+	*addr = data;
+	return 0;
+}
+
+static inline int read_long(struct task_struct *tsk,
+			    unsigned long addr,
+			    unsigned long *result)
+{
+	*result = *(unsigned long *)addr;
+	return 0;
+}
+
+static inline int write_long(struct task_struct *tsk,
+			     unsigned long addr,
+			     unsigned long data)
+{
+	*(unsigned long *) addr = data;
+	return 0;
+}
+
+/*
+ * Called by kernel/ptrace.c when detaching.
+ */
+void ptrace_disable(struct task_struct *child)
+{
+	/* nothing to do */
+}
+
+/*
+ * Read the word at offset "off" into the user area.  We
+ * actually access the pt_regs stored on the kernel stack.
+ */
+static int ptrace_read_user(struct task_struct *tsk, unsigned long off,
+			    unsigned long __user *ret)
+{
+	unsigned long tmp;
+	unsigned long index = off/sizeof(unsigned long);
+
+	if (off & 3)
+		return -EIO;
+
+
+	tmp = 0;
+	if (off < PT_REG_SIZE)
+		tmp = get_reg(tsk, index);
+	else
+		return -EIO;
+
+	return put_user(tmp, ret);
+}
+
+/*
+ * Perform ptrace request
+ */
+long arch_ptrace(struct task_struct *child, long request,
+		 unsigned long addr, unsigned long data)
+{
+	struct pt_regs *regs, newregs;
+	unsigned long tmp;
+	int ret = 0;
+
+	switch (request) {
+		/*
+		 * read word at location "addr" in the child process.
+		 */
+	case PTRACE_PEEKTEXT:
+	case PTRACE_PEEKDATA:
+		ret = read_long(child, addr, &tmp);
+		if (!ret)
+			ret = put_user(tmp, (unsigned long __user *) data);
+		break;
+
+		/*
+		 * read the word at location "addr" in the user registers.
+		 */
+	case PTRACE_PEEKUSR:
+		ret = ptrace_read_user(child, addr, (unsigned long __user *) data);
+		break;
+
+		/*
+		 * write the word at location addr.
+		 */
+	case PTRACE_POKETEXT:
+		ret = write_long(child, addr, data);
+		flush_icache_range(addr, addr + 4);
+		break;
+
+	case PTRACE_POKEDATA:
+		ret = write_long(child, addr, data);
+		break;
+
+		/*
+		 * write the word at location addr in the user registers.
+		 */
+	case PTRACE_POKEUSR:
+		ret = -EIO;
+		if (addr & 3 || addr < 0)
+			break;
+
+		if (addr < PT_REG_SIZE)
+			ret = put_reg(child, (int)addr >> 2, data);
+		break;
+
+		/*
+		 * get all gp regs from the child.
+		 */
+	case PTRACE_GETREGS:
+		regs = task_pt_regs(child);
+		if (copy_to_user((void __user *)data, regs,
+				 sizeof(struct pt_regs)))
+			ret = -EFAULT;
+		break;
+
+		/*
+		 * set all gp regs in the child.
+		 */
+	case PTRACE_SETREGS:
+		ret = -EFAULT;
+		if (copy_from_user(&newregs, (void __user *)data,
+				   sizeof(struct pt_regs)) == 0) {
+			regs = task_pt_regs(child);
+			*regs = newregs;
+			ret = 0;
+		}
+		break;
+
+	default:
+		ret = ptrace_request(child, request, addr, data);
+		break;
+	}
+
+	return ret;
+}
+
+/*
+ * handle tracing of system call entry
+ * - return the revised system call number or ULONG_MAX to cause ENOSYS
+ */
+asmlinkage unsigned long syscall_trace_entry(struct pt_regs *regs)
+{
+	if (tracehook_report_syscall_entry(regs))
+		/* tracing decided this syscall should not happen, so
+		 * We'll return a bogus call number to get an ENOSYS
+		 * error, but leave the original number in
+		 * regs->orig_a4
+		 */
+		return ULONG_MAX;
+
+	return regs->b0;
+}
+
+/*
+ * handle tracing of system call exit
+ */
+asmlinkage void syscall_trace_exit(struct pt_regs *regs)
+{
+	tracehook_report_syscall_exit(regs, 0);
+}
diff --git a/arch/c6x/kernel/setup.c b/arch/c6x/kernel/setup.c
new file mode 100644
index 0000000..8da373e
--- /dev/null
+++ b/arch/c6x/kernel/setup.c
@@ -0,0 +1,550 @@
+/*
+ *  linux/arch/c6x/kernel/setup.c
+ *
+ *  Port on Texas Instruments TMS320C6x architecture
+ *
+ *  Copyright (C) 2004, 2006, 2009, 2010, 2011 Texas Instruments Incorporated
+ *  Author: Aurelien Jacquiot (aurelien.jacquiot@...una.com)
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ *
+ *  This file handles the architecture-dependent parts of system setup
+ */
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/fs.h>
+#include <linux/fb.h>
+#include <linux/genhd.h>
+#include <linux/errno.h>
+#include <linux/console.h>
+#include <linux/string.h>
+#include <linux/delay.h>
+#include <linux/bootmem.h>
+#include <linux/seq_file.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/cache.h>
+#include <linux/pm.h>
+#include <linux/dma-mapping.h>
+
+#ifdef CONFIG_MTD_UCLINUX
+#include <linux/mtd/map.h>
+#include <linux/ext2_fs.h>
+#include <linux/cramfs_fs.h>
+#include <linux/romfs_fs.h>
+#endif
+
+#include <asm/setup.h>
+#include <asm/irq.h>
+#include <asm/hardware.h>
+#include <asm/sections.h>
+
+#include <mach/board.h>
+
+#ifdef CONFIG_BLK_DEV_INITRD
+#include <linux/initrd.h>
+#include <asm/pgtable.h>
+#endif
+
+#include "tags.h"
+
+unsigned long memory_start;
+unsigned long memory_end;
+
+static char c6x_command_line[COMMAND_LINE_SIZE];
+static const char default_command_line[COMMAND_LINE_SIZE] __section(.cmdline) =
+	CONFIG_CMDLINE;
+static const char *cpu_name, *cpu_voltage, *mmu, *fpu, *soc_rev;
+static char __cpu_rev[5], *cpu_rev;
+static size_t initrd_size = CONFIG_BLK_DEV_RAM_SIZE*1024;
+static unsigned int core_id;
+
+#if defined(CONFIG_MTD_PLATRAM) || defined(CONFIG_MTD_PLATRAM_MODULE)
+unsigned int c6x_platram_start;
+unsigned int c6x_platram_size;
+#endif
+
+#if defined(CONFIG_VGA_CONSOLE)
+struct screen_info screen_info;
+#endif
+
+/*
+ * Mach dep functions
+ */
+
+struct tag_header *c6x_tags_pointer __initdata;
+
+unsigned int ticks_per_ns_scaled;
+EXPORT_SYMBOL(ticks_per_ns_scaled);
+
+unsigned int c6x_core_freq;
+EXPORT_SYMBOL(c6x_core_freq);
+
+static void __init get_cpuinfo(void)
+{
+	unsigned cpu_id, rev_id, csr;
+	struct clk *coreclk = clk_get_sys(NULL, "core");
+	unsigned long core_khz;
+
+	if (!IS_ERR(coreclk))
+		c6x_core_freq = clk_get_rate(coreclk);
+	else {
+		printk(KERN_WARNING
+		       "Cannot find core clock frequency. Using 700MHz\n");
+		c6x_core_freq = 700000000;
+	}
+
+	core_khz = c6x_core_freq / 1000;
+
+	ticks_per_ns_scaled =
+		((uint64_t)core_khz << C6X_NDELAY_SCALE) / 1000000;
+
+	csr = get_creg(CSR);
+	cpu_id = csr >> 24;
+	rev_id = (csr >> 16) & 0xff;
+
+	mmu         = "none";
+	cpu_voltage = "unknown";
+
+	switch (cpu_id) {
+	case 0:
+		cpu_name = "C67x";
+		fpu = "yes";
+		break;
+	case 2:
+		cpu_name = "C62x";
+		fpu = "none";
+		break;
+	case 8:
+		cpu_name = "C64x";
+		fpu = "none";
+		break;
+	case 12:
+		cpu_name = "C64x";
+		fpu = "none";
+		break;
+	case 16:
+		cpu_name = "C64x+";
+		cpu_voltage = "1.2";
+		fpu = "none";
+		break;
+	default:
+		cpu_name = "unknown";
+		fpu = "none";
+	}
+
+	if (cpu_id < 16) {
+		switch (rev_id) {
+		case 0x1:
+			if (cpu_id > 8) {
+				cpu_rev = "DM640/DM641/DM642/DM643";
+				cpu_voltage = "1.2 - 1.4";
+			} else {
+				cpu_rev = "C6201";
+				cpu_voltage = "2.5";
+			}
+			break;
+		case 0x2:
+			cpu_rev = "C6201B/C6202/C6211";
+			cpu_voltage = "1.8";
+			break;
+		case 0x3:
+			cpu_rev = "C6202B/C6203/C6204/C6205";
+			cpu_voltage = "1.5";
+			break;
+		case 0x201:
+			cpu_rev = "C6701 revision 0 (early CPU)";
+			cpu_voltage = "1.8";
+			break;
+		case 0x202:
+			cpu_rev = "C6701/C6711/C6712";
+			cpu_voltage = "1.8";
+			break;
+		case 0x801:
+			cpu_rev = "C64x";
+			cpu_voltage = "1.5";
+			break;
+		default:
+			cpu_rev = "unknown";
+		}
+	} else {
+		cpu_rev = __cpu_rev;
+		snprintf(__cpu_rev, sizeof(__cpu_rev), "0x%x", cpu_id);
+	}
+
+	core_id = get_coreid();
+
+	printk(KERN_INFO "CPU%d: %s rev %s, %s volts, %uMHz\n",
+	       core_id, cpu_name, cpu_rev,
+	       cpu_voltage, c6x_core_freq / 1000000);
+#ifdef C6X_SOC_HAS_CORE_REV
+	soc_rev = arch_compute_silicon_rev(arch_get_silicon_rev());
+#else
+	soc_rev = "unknown";
+#endif
+}
+
+#ifdef CONFIG_TMS320C6X_CACHES_ON
+/*
+ * L1 and L2 caches configuration
+ */
+static void cache_init(void)
+{
+	/* Set L2 caches on the the whole L2 SRAM memory */
+	L2_cache_set_mode(L2MODE_SIZE);
+
+	/* Enable L1 */
+	L1_cache_on();
+}
+#endif /* CONFIG_TMS320C6X_CACHES_ON */
+
+static void cache_set(unsigned int start, unsigned int end)
+{
+#ifdef CONFIG_XIP_KERNEL
+	unsigned long _data_len = (unsigned long)__init_end -
+		(unsigned long)_sdata - 1;
+#endif
+
+	/* Set the whole external memory as non-cacheable */
+	disable_caching(RAM_MEMORY_START,
+			RAM_MEMORY_START + BOARD_RAM_SIZE - 1);
+	/*
+	 * Then set the external memory used by this Linux instance cacheable.
+	 * DMA coherent memory region will be set as non-cacheable later.
+	 */
+	enable_caching(CACHE_REGION_START(start),
+		       CACHE_REGION_START(end - 1));
+
+#ifdef CONFIG_XIP_KERNEL
+	/* Also for XIP, make kernel code cacheable if in RAM */
+	if (CONFIG_XIP_KERNEL_TEXT_ADDR >= RAM_MEMORY_START &&
+	    CONFIG_XIP_KERNEL_TEXT_ADDR < (RAM_MEMORY_START + BOARD_RAM_SIZE))
+		enable_caching(CACHE_REGION_START(CONFIG_XIP_KERNEL_TEXT_ADDR),
+			       CACHE_REGION_START((unsigned long)_data_lma +
+						  _data_len));
+#endif
+}
+
+#ifdef CONFIG_XIP_KERNEL
+void __init c6x_relocate_xip_data(void)
+{
+	memcpy(_sdata, _data_lma,
+	       (unsigned long)__init_end - (unsigned long)_sdata);
+}
+#endif
+
+/*
+ * Early parsing of the command line
+ */
+static int userdef __initdata;
+
+/* "mem=" parsing. */
+static int __init early_mem(char *p)
+{
+	u32 mem_size;
+
+	if (!p)
+		return -EINVAL;
+
+	mem_size = memparse(p, &p);
+	/* don't remove all of memory when handling "mem={invalid}" */
+	if (mem_size == 0)
+		return -EINVAL;
+
+	userdef = 1;
+	memory_end = PAGE_ALIGN(PAGE_OFFSET + mem_size);
+
+	return 0;
+}
+early_param("mem", early_mem);
+
+/* "memdma=" parsing. */
+static int __init early_memdma(char *p)
+{
+	if (!p)
+		return -EINVAL;
+
+	dma_memory_size = memparse(p, &p);
+	if (*p == '@')
+		dma_memory_start = memparse(p, &p);
+
+	return 0;
+}
+early_param("memdma", early_memdma);
+
+#ifdef CONFIG_BLK_DEV_INITRD
+/* "initrd=" parsing. */
+static int __init early_initrd(char *p)
+{
+	if (!p)
+		return -EINVAL;
+
+	initrd_start = memparse(p, &p);
+	if (*p == ',')
+		initrd_size = memparse(p + 1, &p);
+
+	return 0;
+}
+early_param("initrd", early_initrd);
+#endif /* CONFIG_BLK_DEV_INITRD */
+
+#if defined(CONFIG_MTD_PLATRAM) || defined(CONFIG_MTD_PLATRAM_MODULE)
+/* "platram=" parsing. */
+static int __init early_platram(char *p)
+{
+	if (!p)
+		return -EINVAL;
+
+	c6x_platram_start = memparse(p, &p);
+	if (*p == ',')
+		c6x_platram_size = memparse(p + 1, &p);
+
+	return 0;
+}
+early_param("platram", early_platram);
+#endif
+
+#ifdef CONFIG_MTD_UCLINUX
+static unsigned long get_romfs_size(void *addr)
+{
+#ifdef CONFIG_ROMFS_FS
+	if ((*((unsigned long *)addr) == ROMSB_WORD0) &&
+	    (*((unsigned long *)addr + 1) == ROMSB_WORD1))
+		return PAGE_ALIGN(be32_to_cpu(*((unsigned long *)addr + 2)));
+#endif
+
+#ifdef CONFIG_CRAMFS
+	if (*((unsigned long *)addr) == CRAMFS_MAGIC)
+		return PAGE_ALIGN(*((unsigned long *)addr + 1));
+#endif
+
+#if defined(CONFIG_EXT2_FS) || defined(CONFIG_EXT3_FS)
+	if (le16_to_cpu(*((unsigned short *)addr + 0x21c)) == EXT2_SUPER_MAGIC)
+		return PAGE_ALIGN(le32_to_cpu((*((unsigned long *)addr +
+						 0x101))) * 1024);
+#endif
+
+	return 0;
+}
+
+/*
+ * This is called just before .bss is cleared so that any MTD_UCLINUX
+ * filesystem located in bss can be moved out of the way first.
+ */
+void __init c6x_mtd_early_init(void)
+{
+	unsigned int romfs_size;
+
+	romfs_size = PAGE_ALIGN(get_romfs_size((unsigned *)&__bss_start));
+
+	/* Move ROMFS out of BSS */
+	if (romfs_size)
+		memmove(&_ebss, (int *)&__bss_start, romfs_size);
+}
+
+#endif /* CONFIG_MTD_UCLINUX */
+
+void __init setup_arch(char **cmdline_p)
+{
+	int bootmap_size;
+	struct tag_cmdline *tcmd;
+#if defined(CONFIG_MTD_UCLINUX)
+	unsigned long romfs_size;
+#endif
+
+	if (!c6x_tags_are_valid(c6x_tags_pointer))
+		c6x_tags_pointer = NULL;
+
+	/* interrupts must be masked */
+	local_irq_disable();
+
+	/*
+	 * Set the Interrupt Service Table (IST) to the beginning of the
+	 * vector table.
+	 */
+	set_ist(_vectors_start);
+
+#ifdef CONFIG_TMS320C6X_CACHES_ON
+	/* Perform caches initialization */
+	cache_init();
+#endif
+
+	/* Initialise C6x IRQs */
+	set_creg(IER, 2);
+
+	/* Set peripheral power-down */
+#ifdef CONFIG_PM
+	pwr_pdctl_set(PWR_PDCTL_ALL);
+#endif
+
+	/* Call SOC configuration function */
+	c6x_soc_setup_arch();
+
+	/* Call board configuration function */
+	c6x_board_setup_arch();
+
+	/* Get CPU info */
+	get_cpuinfo();
+
+	/* Memory management */
+	printk(KERN_INFO "Initializing kernel\n");
+
+#if defined(CONFIG_MTD_UCLINUX)
+	romfs_size = get_romfs_size(&_ebss);
+	memory_start = PAGE_ALIGN(((unsigned int) &_ebss) + romfs_size);
+
+	uclinux_ram_map.phys = (unsigned long)&_ebss;
+	uclinux_ram_map.size = romfs_size;
+#else
+	memory_start = PAGE_ALIGN((unsigned int) &_end);
+#endif
+
+	memory_end   = PAGE_ALIGN(RAM_MEMORY_START + BOARD_RAM_SIZE);
+
+	init_mm.start_code = (unsigned long) &_stext;
+	init_mm.end_code   = (unsigned long) &_etext;
+#if defined(CONFIG_MTD_UCLINUX)
+	init_mm.end_data   = (unsigned long) (((unsigned long) &_ebss) +
+					      romfs_size);
+	init_mm.brk        = (unsigned long) (((unsigned long) &_ebss) +
+					      romfs_size);
+#else
+	init_mm.end_data   = (unsigned long) &_edata;
+	init_mm.brk        = (unsigned long) &_end;
+#endif
+
+	/* Initialize command line */
+	strlcpy(c6x_command_line, default_command_line, COMMAND_LINE_SIZE);
+	*cmdline_p = c6x_command_line;
+
+	/* Let cmdline passed through tag array override CONFIG_CMDLINE */
+	tcmd = c6x_tag_find(c6x_tags_pointer, TAG_CMDLINE);
+	if (tcmd)
+		strlcpy(c6x_command_line, tcmd->cmdline, COMMAND_LINE_SIZE);
+
+	/* parse_early_param needs a boot_command_line */
+	strlcpy(boot_command_line, c6x_command_line, COMMAND_LINE_SIZE);
+
+	parse_early_param();
+
+	if (userdef)
+		printk(KERN_INFO "Physical RAM map changed by user\n");
+
+	/* Set caching of external RAM used by Linux */
+	cache_set(PAGE_OFFSET, memory_end);
+
+	/* Initialize the coherent memory */
+	coherent_mem_init();
+
+	/*
+	 * Give all the memory to the bootmap allocator,  tell it to put the
+	 * boot mem_map at the start of memory
+	 */
+	bootmap_size = init_bootmem_node(NODE_DATA(0),
+					 memory_start >> PAGE_SHIFT,
+					 PAGE_OFFSET >> PAGE_SHIFT,
+					 memory_end >> PAGE_SHIFT);
+
+	/*
+	 * Free the usable memory,  we have to make sure we do not free
+	 * the bootmem bitmap so we then reserve it after freeing it :-)
+	 */
+	free_bootmem(memory_start, memory_end - memory_start);
+	reserve_bootmem(memory_start, bootmap_size, BOOTMEM_DEFAULT);
+
+	max_low_pfn = PFN_DOWN(memory_end);
+	min_low_pfn = PFN_UP(memory_start);
+	max_mapnr = max_low_pfn - min_low_pfn;
+
+#if defined(CONFIG_MTD_PLATRAM) || defined(CONFIG_MTD_PLATRAM_MODULE)
+	if (c6x_platram_size) {
+		if (c6x_platram_start < (memory_start + bootmap_size) ||
+		    (c6x_platram_start + c6x_platram_size) > memory_end) {
+			printk(KERN_ERR "Invalid platram= argument. "
+			       "Out of range %p - %p!\n",
+			       (void *)memory_start, (void *)memory_end);
+			c6x_platram_size = 0;
+		} else
+			reserve_bootmem(c6x_platram_start, c6x_platram_size,
+					BOOTMEM_DEFAULT);
+	}
+#endif
+
+#ifdef CONFIG_BLK_DEV_INITRD
+	if (initrd_start) {
+		if (initrd_start >= memory_start &&
+		    (initrd_start + initrd_size) <= memory_end) {
+			reserve_bootmem(initrd_start, initrd_size,
+					BOOTMEM_DEFAULT);
+			initrd_end = initrd_start+initrd_size;
+		} else {
+			printk(KERN_ERR
+			       "initrd is not contained in normal memory\n"
+			       "initrd=(0x%08lx:0x%08lx) normal_mem=(%p:%p)\n"
+			       "disabling initrd\n",
+			       initrd_start, initrd_start + initrd_size,
+			       (void *)memory_start, (void *)memory_end);
+			initrd_start = 0;
+		}
+	} else
+		printk(KERN_INFO "no initrd specified\n");
+#endif
+
+	/* Get kmalloc into gear */
+	paging_init();
+
+#if defined(CONFIG_VT) && defined(CONFIG_DUMMY_CONSOLE)
+	conswitchp = &dummy_con;
+#endif
+}
+
+static int show_cpuinfo(struct seq_file *m, void *v)
+{
+	seq_printf(m,
+		   "CPU:\t\t%s\n"
+		   "Core revision:\t%s\n"
+		   "Core voltage:\t%s\n"
+		   "Core id:\t%d\n"
+		   "SoC cores:\t%d\n"
+		   "MMU:\t\t%s\n"
+		   "FPU:\t\t%s\n"
+		   "Silicon rev:\t%s\n"
+		   "Clocking:\t%uMHz\n"
+		   "BogoMips:\t%lu.%02lu\n"
+		   "Calibration:\t%lu loops\n",
+		   cpu_name, cpu_rev, cpu_voltage, core_id, CORE_NUM, mmu, fpu,
+		   soc_rev, (c6x_core_freq + 500000) / 1000000,
+		   (loops_per_jiffy/(500000/HZ)),
+		   (loops_per_jiffy/(5000/HZ))%100,
+		   loops_per_jiffy);
+
+	return 0;
+}
+
+static void *c_start(struct seq_file *m, loff_t *pos)
+{
+	return *pos < 1 ? (void *)1 : NULL;
+}
+static void *c_next(struct seq_file *m, void *v, loff_t *pos)
+{
+	++*pos;
+	return NULL;
+}
+static void c_stop(struct seq_file *m, void *v)
+{
+}
+
+const struct seq_operations cpuinfo_op = {
+	c_start,
+	c_stop,
+	c_next,
+	show_cpuinfo
+};
+
diff --git a/arch/c6x/kernel/signal.c b/arch/c6x/kernel/signal.c
new file mode 100644
index 0000000..252c9ec
--- /dev/null
+++ b/arch/c6x/kernel/signal.c
@@ -0,0 +1,384 @@
+/*
+ *  linux/arch/c6x/kernel/signal.c
+ *
+ *  Port on Texas Instruments TMS320C6x architecture
+ *
+ *  Copyright (C) 2004, 2006, 2009, 2010, 2011 Texas Instruments Incorporated
+ *  Author: Aurelien Jacquiot (aurelien.jacquiot@...una.com)
+ *
+ *  Updated for 2.6.34: Mark Salter <msalter@...hat.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ */
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/kernel.h>
+#include <linux/signal.h>
+#include <linux/errno.h>
+#include <linux/wait.h>
+#include <linux/ptrace.h>
+#include <linux/unistd.h>
+#include <linux/stddef.h>
+#include <linux/highuid.h>
+#include <linux/personality.h>
+#include <linux/tracehook.h>
+#include <linux/uaccess.h>
+#include <linux/syscalls.h>
+
+#include <asm/setup.h>
+#include <asm/segment.h>
+#include <asm/ucontext.h>
+#include <asm/pgtable.h>
+#include <asm/pgalloc.h>
+#include <asm/traps.h>
+#include <asm/cacheflush.h>
+
+#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
+
+/*
+ * Do a signal return, undo the signal stack.
+ */
+
+#define RETCODE_SIZE (9 << 2)	/* 9 instructions = 36 bytes */
+
+struct rt_sigframe {
+	struct siginfo __user *pinfo;
+	void __user *puc;
+	struct siginfo info;
+	struct ucontext uc;
+	unsigned long retcode[RETCODE_SIZE >> 2];
+};
+
+static int restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc)
+{
+	int err = 0;
+
+#define COPY(x)  (err |= __get_user(regs->x, &sc->sc_##x))
+
+	COPY(sp); COPY(a4); COPY(b4); COPY(a6); COPY(b6); COPY(a8); COPY(b8);
+	COPY(a0); COPY(a1); COPY(a2); COPY(a3); COPY(a5); COPY(a7); COPY(a9);
+	COPY(b0); COPY(b1); COPY(b2); COPY(b3); COPY(b5); COPY(b7); COPY(b9);
+
+	COPY(a16); COPY(a17); COPY(a18); COPY(a19);
+	COPY(a20); COPY(a21); COPY(a22); COPY(a23);
+	COPY(a24); COPY(a25); COPY(a26); COPY(a27);
+	COPY(a28); COPY(a29); COPY(a30); COPY(a31);
+	COPY(b16); COPY(b17); COPY(b18); COPY(b19);
+	COPY(b20); COPY(b21); COPY(b22); COPY(b23);
+	COPY(b24); COPY(b25); COPY(b26); COPY(b27);
+	COPY(b28); COPY(b29); COPY(b30); COPY(b31);
+
+	COPY(csr); COPY(pc);
+
+#undef COPY
+
+	return err;
+}
+
+asmlinkage int do_rt_sigreturn(struct pt_regs *regs)
+{
+	struct rt_sigframe __user *frame;
+	sigset_t set;
+
+	/*
+	 * Since we stacked the signal on a dword boundary,
+	 * then 'sp' should be dword aligned here.  If it's
+	 * not, then the user is trying to mess with us.
+	 */
+	if (regs->sp & 7)
+		goto badframe;
+
+	frame = (struct rt_sigframe __user *) ((unsigned long) regs->sp + 8);
+
+	if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
+		goto badframe;
+	if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
+		goto badframe;
+
+	sigdelsetmask(&set, ~_BLOCKABLE);
+	spin_lock_irq(&current->sighand->siglock);
+	current->blocked = set;
+	recalc_sigpending();
+	spin_unlock_irq(&current->sighand->siglock);
+
+	if (restore_sigcontext(regs, &frame->uc.uc_mcontext))
+		goto badframe;
+
+	return regs->a4;
+
+badframe:
+	force_sig(SIGSEGV, current);
+	return 0;
+}
+
+static int
+setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs,
+		 unsigned long mask)
+{
+	int err = 0;
+
+	err |= __put_user(mask, &sc->sc_mask);
+
+#define COPY(x) (err |= __put_user(regs->x, &sc->sc_##x))
+
+	COPY(sp); COPY(a4); COPY(b4); COPY(a6); COPY(b6); COPY(a8); COPY(b8);
+	COPY(a0); COPY(a1); COPY(a2); COPY(a3); COPY(a5); COPY(a7); COPY(a9);
+	COPY(b0); COPY(b1); COPY(b2); COPY(b3); COPY(b5); COPY(b7); COPY(b9);
+
+	COPY(a16); COPY(a17); COPY(a18); COPY(a19);
+	COPY(a20); COPY(a21); COPY(a22); COPY(a23);
+	COPY(a24); COPY(a25); COPY(a26); COPY(a27);
+	COPY(a28); COPY(a29); COPY(a30); COPY(a31);
+	COPY(b16); COPY(b17); COPY(b18); COPY(b19);
+	COPY(b20); COPY(b21); COPY(b22); COPY(b23);
+	COPY(b24); COPY(b25); COPY(b26); COPY(b27);
+	COPY(b28); COPY(b29); COPY(b30); COPY(b31);
+
+	COPY(csr); COPY(pc);
+
+#undef COPY
+
+	return err;
+}
+
+static inline void __user *get_sigframe(struct k_sigaction *ka,
+					struct pt_regs *regs,
+					unsigned long framesize)
+{
+	unsigned long sp = regs->sp;
+
+	/*
+	 * This is the X/Open sanctioned signal stack switching.
+	 */
+	if ((ka->sa.sa_flags & SA_ONSTACK) && sas_ss_flags(sp) == 0)
+		sp = current->sas_ss_sp + current->sas_ss_size;
+
+	/*
+	 * No matter what happens, 'sp' must be dword
+	 * aligned otherwise nasty things will happen
+	 */
+	return (void __user *)((sp - framesize) & ~7);
+}
+
+static int setup_rt_frame(int signr, struct k_sigaction *ka, siginfo_t *info,
+			   sigset_t *set, struct pt_regs *regs)
+{
+	struct rt_sigframe __user *frame;
+	unsigned long __user *retcode;
+	int err = 0;
+
+	frame = get_sigframe(ka, regs, sizeof(*frame));
+
+	if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
+		goto segv_and_exit;
+
+	err |= __put_user(&frame->info, &frame->pinfo);
+	err |= __put_user(&frame->uc, &frame->puc);
+	err |= copy_siginfo_to_user(&frame->info, info);
+
+	/* Clear all the bits of the ucontext we don't use.  */
+	err |= __clear_user(&frame->uc, offsetof(struct ucontext, uc_mcontext));
+
+	err |= setup_sigcontext(&frame->uc.uc_mcontext,	regs, set->sig[0]);
+	err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
+
+	/* Set up to return from userspace */
+	retcode = (unsigned long __user *) &frame->retcode;
+	err |= put_user(0x0000002AUL | (__NR_rt_sigreturn << 7), retcode++);
+						  /* MVK __NR_rt_sigreturn,B0 */
+	err |= put_user(0x10000000UL, retcode++); /* SWE */
+	err |= put_user(0x00006000UL, retcode++); /* NOP 4 */
+	err |= put_user(0x00006000UL, retcode++); /* NOP 4 */
+	err |= put_user(0x00006000UL, retcode++); /* NOP 4 */
+	err |= put_user(0x00006000UL, retcode++); /* NOP 4 */
+	err |= put_user(0x00006000UL, retcode++); /* NOP 4 */
+	err |= put_user(0x00006000UL, retcode++); /* NOP 4 */
+	err |= put_user(0x00006000UL, retcode++); /* NOP 4 */
+
+	if (err)
+		goto segv_and_exit;
+
+	flush_icache_range((unsigned long) &frame->retcode,
+			   (unsigned long) &frame->retcode + RETCODE_SIZE);
+
+	retcode = (unsigned long __user *) &frame->retcode;
+
+	/* Change user context to branch to signal handler */
+	regs->sp = (unsigned long) frame - 8;
+	regs->b3 = (unsigned long) retcode;
+	regs->pc = (unsigned long) ka->sa.sa_handler;
+
+	/* Give the signal number to the handler */
+	regs->a4 = signr;
+
+	/*
+	 * For realtime signals we must also set the second and third
+	 * arguments for the signal handler.
+	 *   -- Peter Maydell <pmaydell@...ark.greenend.org.uk> 2000-12-06
+	 */
+	regs->b4 = (unsigned long)&frame->info;
+	regs->a6 = (unsigned long)&frame->uc;
+
+	return 0;
+
+segv_and_exit:
+	force_sig(SIGSEGV, current);
+	return -EFAULT;
+}
+
+static inline void
+handle_restart(struct pt_regs *regs, struct k_sigaction *ka, int has_handler)
+{
+	switch (regs->a4) {
+	case -ERESTARTNOHAND:
+		if (!has_handler)
+			goto do_restart;
+		regs->a4 = -EINTR;
+		break;
+
+	case -ERESTARTSYS:
+		if (has_handler && !(ka->sa.sa_flags & SA_RESTART)) {
+			regs->a4 = -EINTR;
+			break;
+		}
+	/* fallthrough */
+	case -ERESTARTNOINTR:
+do_restart:
+		regs->a4 = regs->orig_a4;
+		regs->pc -= 4;
+		break;
+	}
+}
+
+/*
+ * handle the actual delivery of a signal to userspace
+ */
+static int handle_signal(int sig,
+			 siginfo_t *info, struct k_sigaction *ka,
+			 sigset_t *oldset, struct pt_regs *regs,
+			 int syscall)
+{
+	int ret;
+
+	/* Are we from a system call? */
+	if (syscall) {
+		/* If so, check system call restarting.. */
+		switch (regs->a4) {
+		case -ERESTART_RESTARTBLOCK:
+		case -ERESTARTNOHAND:
+			regs->a4 = -EINTR;
+			break;
+
+		case -ERESTARTSYS:
+			if (!(ka->sa.sa_flags & SA_RESTART)) {
+				regs->a4 = -EINTR;
+				break;
+			}
+
+			/* fallthrough */
+		case -ERESTARTNOINTR:
+			regs->a4 = regs->orig_a4;
+			regs->pc -= 4;
+		}
+	}
+
+	/* Set up the stack frame */
+	ret = setup_rt_frame(sig, ka, info, oldset, regs);
+	if (ret == 0) {
+		spin_lock_irq(&current->sighand->siglock);
+		sigorsets(&current->blocked, &current->blocked,
+			  &ka->sa.sa_mask);
+		if (!(ka->sa.sa_flags & SA_NODEFER))
+			sigaddset(&current->blocked, sig);
+		recalc_sigpending();
+		spin_unlock_irq(&current->sighand->siglock);
+	}
+
+	return ret;
+}
+
+/*
+ * handle a potential signal
+ */
+static void do_signal(struct pt_regs *regs, int syscall)
+{
+	struct k_sigaction ka;
+	siginfo_t info;
+	sigset_t *oldset;
+	int signr;
+
+	/* we want the common case to go fast, which is why we may in certain
+	 * cases get here from kernel mode */
+	if (!user_mode(regs))
+		return;
+
+	if (test_thread_flag(TIF_RESTORE_SIGMASK))
+		oldset = &current->saved_sigmask;
+	else
+		oldset = &current->blocked;
+
+	signr = get_signal_to_deliver(&info, &ka, regs, NULL);
+	if (signr > 0) {
+		if (handle_signal(signr, &info, &ka, oldset,
+				  regs, syscall) == 0) {
+			/* a signal was successfully delivered; the saved
+			 * sigmask will have been stored in the signal frame,
+			 * and will be restored by sigreturn, so we can simply
+			 * clear the TIF_RESTORE_SIGMASK flag */
+			if (test_thread_flag(TIF_RESTORE_SIGMASK))
+				clear_thread_flag(TIF_RESTORE_SIGMASK);
+
+			tracehook_signal_handler(signr, &info, &ka, regs, 0);
+		}
+
+		return;
+	}
+
+	/* did we come from a system call? */
+	if (syscall) {
+		/* restart the system call - no handlers present */
+		switch (regs->a4) {
+		case -ERESTARTNOHAND:
+		case -ERESTARTSYS:
+		case -ERESTARTNOINTR:
+			regs->a4 = regs->orig_a4;
+			regs->pc -= 4;
+			break;
+
+		case -ERESTART_RESTARTBLOCK:
+			regs->a4 = regs->orig_a4;
+			regs->b0 = __NR_restart_syscall;
+			regs->pc -= 4;
+			break;
+		}
+	}
+
+	/* if there's no signal to deliver, we just put the saved sigmask
+	 * back */
+	if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
+		clear_thread_flag(TIF_RESTORE_SIGMASK);
+		sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
+	}
+}
+
+/*
+ * notification of userspace execution resumption
+ * - triggered by current->work.notify_resume
+ */
+asmlinkage void do_notify_resume(struct pt_regs *regs, u32 thread_info_flags,
+				 int syscall)
+{
+	/* deal with pending signal delivery */
+	if (thread_info_flags & ((1 << TIF_SIGPENDING) |
+				 (1 << TIF_RESTORE_SIGMASK)))
+		do_signal(regs, syscall);
+
+	if (thread_info_flags & (1 << TIF_NOTIFY_RESUME)) {
+		clear_thread_flag(TIF_NOTIFY_RESUME);
+		tracehook_notify_resume(regs);
+		if (current->replacement_session_keyring)
+			key_replace_session_keyring();
+	}
+}
diff --git a/arch/c6x/kernel/switch_to.S b/arch/c6x/kernel/switch_to.S
new file mode 100644
index 0000000..06a41bb
--- /dev/null
+++ b/arch/c6x/kernel/switch_to.S
@@ -0,0 +1,67 @@
+/*
+ *  Copyright (C) 2011 Texas Instruments Incorporated
+ *  Author: Mark Salter (msalter@...hat.com)
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ */
+
+#include <asm/asm-offsets.h>
+
+#define SP	B15
+
+	/*
+	 * void __switch_to(struct thread_info *prev,
+	 *      	    struct thread_info *next,
+	 *		    struct task_struct *tsk) ;
+	 */
+	.global __switch_to
+__switch_to:
+
+	LDDW	.D2T2	*+B4(THREAD_B15_14),B7:B6
+ ||	MV	.L2X	A4,B5	; prev
+ ||	MV	.L1X	B4,A5	; next
+ ||	MVC	.S2	RILC,B1
+
+	STW	.D2T2	B3,*+B5(THREAD_PC)
+ ||	STDW	.D1T1	A13:A12,*+A4(THREAD_A13_12)
+ ||	MVC	.S2	ILC,B0
+
+	LDW	.D2T2	*+B4(THREAD_PC),B3
+ ||	LDDW	.D1T1	*+A5(THREAD_A13_12),A13:A12
+
+	STDW	.D1T1	A11:A10,*+A4(THREAD_A11_10)
+ ||	STDW	.D2T2	B1:B0,*+B5(THREAD_RICL_ICL)
+ ||	MVKL	.S2	current_ksp,B1
+
+	STDW	.D2T2	B15:B14,*+B5(THREAD_B15_14)
+ ||	STDW	.D1T1	A15:A14,*+A4(THREAD_A15_14)
+ ||	MVKH	.S2	current_ksp,B1
+
+	;; Switch to next SP
+	MV	.S2	B7,SP
+ ||	STW	.D2T2	B7,*B1
+ ||	MV	.L2	B6,B14
+ ||	LDDW	.D1T1	*+A5(THREAD_RICL_ICL),A1:A0
+
+	STDW	.D2T2	B11:B10,*+B5(THREAD_B11_10)
+ ||	LDDW	.D1T1	*+A5(THREAD_A15_14),A15:A14
+
+	STDW	.D2T2	B13:B12,*+B5(THREAD_B13_12)
+ ||	LDDW	.D1T1	*+A5(THREAD_A11_10),A11:A10
+
+	B	.S2	B3		; return in next E1
+ ||	LDDW	.D2T2	*+B4(THREAD_B13_12),B13:B12
+
+	LDDW	.D2T2	*+B4(THREAD_B11_10),B11:B10
+	NOP
+
+	MV	.L2X	A0,B0
+ ||	MV	.S1	A6,A4
+
+	MVC	.S2	B0,ILC
+ ||	MV	.L2X	A1,B1
+
+	MVC	.S2	B1,RILC
+
diff --git a/arch/c6x/kernel/sys_c6x.c b/arch/c6x/kernel/sys_c6x.c
new file mode 100644
index 0000000..5d0ee49
--- /dev/null
+++ b/arch/c6x/kernel/sys_c6x.c
@@ -0,0 +1,111 @@
+/*
+ *  linux/arch/c6x/kernel/sys_c6x.c
+ *
+ *  Port on Texas Instruments TMS320C6x architecture
+ *
+ *  Copyright (C) 2004, 2009, 2010, 2011 Texas Instruments Incorporated
+ *  Author: Aurelien Jacquiot (aurelien.jacquiot@...una.com)
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ *
+ *  This file contains various random system calls that
+ *  have a non-standard calling sequence on the C6x platform.
+ */
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/smp.h>
+#include <linux/sem.h>
+#include <linux/msg.h>
+#include <linux/shm.h>
+#include <linux/stat.h>
+#include <linux/slab.h>
+#include <linux/mman.h>
+#include <linux/file.h>
+#include <linux/utsname.h>
+#include <linux/module.h>
+#include <linux/syscalls.h>
+#include <linux/mtd/map.h>
+#include <linux/stringify.h>
+#include <linux/uaccess.h>
+
+#include <asm/setup.h>
+#include <asm/segment.h>
+#include <asm/traps.h>
+#include <asm/page.h>
+#include <asm/syscalls.h>
+
+#ifdef CONFIG_ACCESS_CHECK
+int _access_ok(unsigned long addr, unsigned long size)
+{
+	if (!size)
+		return 1;
+
+	if (!addr || addr > (0xffffffffUL - (size - 1)))
+		goto _bad_access;
+
+	if (segment_eq(get_fs(), KERNEL_DS))
+		return 1;
+
+	if (memory_start <= addr && (addr + size - 1) < memory_end)
+		return 1;
+
+_bad_access:
+#if 0
+	printk(KERN_CRIT "**Bad access attempt: pid[%d] addr[%p] size[0x%x]\n",
+	       current->pid, addr, size);
+#endif
+	return 0;
+}
+EXPORT_SYMBOL(_access_ok);
+#endif
+
+/* sys_cache_sync -- sync caches over given range */
+asmlinkage int sys_cache_sync(unsigned long s, unsigned long e)
+{
+	/* FIXME. Add range checks */
+
+	L1D_cache_block_writeback_invalidate(s, e);
+	L1P_cache_block_invalidate(s, e);
+
+	return 0;
+}
+
+asmlinkage long sys_mmap(unsigned long addr, unsigned long len,
+			 unsigned long prot, unsigned long flags,
+			 unsigned long fd, off_t offset)
+{
+	if (offset & ~PAGE_MASK)
+		return -EINVAL;
+	return sys_mmap_pgoff(addr, len, prot, flags, fd, offset >> PAGE_SHIFT);
+}
+
+/* Provide the actual syscall number to call mapping. */
+#undef __SYSCALL
+#define __SYSCALL(nr, call) [nr] = (call),
+
+/*
+ * Use trampolines
+ */
+#define sys_pread64		sys_pread_c6x
+#define sys_pwrite64		sys_pwrite_c6x
+#define sys_truncate64		sys_truncate64_c6x
+#define sys_ftruncate64		sys_ftruncate64_c6x
+#define sys_fadvise64		sys_fadvise64_c6x
+#define sys_fadvise64_64	sys_fadvise64_64_c6x
+#define sys_fallocate		sys_fallocate_c6x
+
+/* Use sys_mmap_pgoff directly */
+#define sys_mmap2 sys_mmap_pgoff
+
+/*
+ * Note that we can't include <linux/unistd.h> here since the header
+ * guard will defeat us; <asm/unistd.h> checks for __SYSCALL as well.
+ */
+void *sys_call_table[__NR_syscalls] = {
+	[0 ... __NR_syscalls-1] = sys_ni_syscall,
+#include <asm/unistd.h>
+};
+
diff --git a/arch/c6x/kernel/tags.c b/arch/c6x/kernel/tags.c
new file mode 100644
index 0000000..bb1064a
--- /dev/null
+++ b/arch/c6x/kernel/tags.c
@@ -0,0 +1,98 @@
+/*
+ * tags.c
+ *
+ * This file is provided under a dual BSD/GPLv2 license.  When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * Author: Mark Salter <msalter@...hat.com>
+ *
+ * GPLv2 LICENSE SUMMARY
+ *
+ * Copyright (C) 2010 Texas Instruments Incorporated
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
+ * USA
+ *
+ * BSD LICENSE
+ *
+ * Copyright (C) 2010 Texas Instruments Incorporated
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *  * Neither the name Texas Instruments nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+#include <linux/types.h>
+
+#include "tags.h"
+
+#define TAG_NEXT(p) \
+	((struct tag_header *)((char *)p + (((struct tag_header *)p)->size) \
+			       + sizeof(struct tag_header)))
+
+struct tag_header *c6x_tag_next(struct tag_header *atag)
+{
+	if (atag->tag == TAG_EOL)
+		return NULL;
+
+	atag = TAG_NEXT(atag);
+	if (atag->tag == TAG_EOL)
+		return NULL;
+
+	return atag;
+}
+
+void *c6x_tag_find(struct tag_header *atag, unsigned int tag)
+{
+	while (atag && atag->tag != TAG_EOL && atag->tag != tag)
+		atag = c6x_tag_next(atag);
+	if (atag && atag->tag == tag)
+		return (void *)((unsigned long)atag + sizeof(*atag));
+	return NULL;
+}
+
+int c6x_tags_are_valid(struct tag_header *atag)
+{
+	if (!atag)
+		return 0;
+
+	if (atag->tag != TAG_SOL || atag->size)
+		return 0;
+
+	return 1;
+}
+
+
diff --git a/arch/c6x/kernel/tags.h b/arch/c6x/kernel/tags.h
new file mode 100644
index 0000000..9c4496d
--- /dev/null
+++ b/arch/c6x/kernel/tags.h
@@ -0,0 +1,82 @@
+/*
+ * tags.h
+ *
+ * This file is provided under a dual BSD/GPLv2 license.  When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * Author: Mark Salter <msalter@...hat.com>
+ *
+ * GPLv2 LICENSE SUMMARY
+ *
+ * Copyright (C) 2010 Texas Instruments Incorporated
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
+ * USA
+ *
+ * BSD LICENSE
+ *
+ * Copyright (C) 2010 Texas Instruments Incorporated
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *  * Neither the name Texas Instruments nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#define TAGS_MAGIC	0x54694265
+
+/* The list must start with an TAG_SOL */
+#define TAG_SOL		0x64000001
+
+/* The list must end with an TAG_EOL */
+#define TAG_EOL		0x64000002
+
+#define TAG_CMDLINE	0x64000003
+
+#ifndef __ASSEMBLY__
+struct tag_header {
+	unsigned int size;
+	unsigned int tag;
+};
+
+struct tag_cmdline {
+	char	cmdline[0];
+};
+
+extern int c6x_tags_are_valid(struct tag_header *atag);
+extern struct tag_header *c6x_tag_next(struct tag_header *atag);
+extern void *c6x_tag_find(struct tag_header *atag, unsigned int tag);
+#endif
diff --git a/arch/c6x/kernel/time.c b/arch/c6x/kernel/time.c
new file mode 100644
index 0000000..d969b48
--- /dev/null
+++ b/arch/c6x/kernel/time.c
@@ -0,0 +1,55 @@
+/*
+ *  linux/arch/c6x/kernel/time.c
+ *
+ *  Port on Texas Instruments TMS320C6x architecture
+ *
+ *  Copyright (C) 2004, 2009, 2010 Texas Instruments Incorporated
+ *  Author: Aurelien Jacquiot (aurelien.jacquiot@...una.com)
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ */
+
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/param.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/interrupt.h>
+
+#include <asm/segment.h>
+#include <linux/io.h>
+#include <asm/irq.h>
+#include <asm/timer.h>
+
+#include <linux/timex.h>
+#include <linux/profile.h>
+
+static u32 sched_clock_multiplier;
+#define SCHED_CLOCK_SHIFT 16
+
+/*
+ * scheduler clock - returns current time in nanosec units.
+ */
+u64 sched_clock(void)
+{
+	u64 tsc;
+
+	/* read the TSC value
+	 */
+	tsc = get_cycles();
+
+	return (tsc * sched_clock_multiplier) >> SCHED_CLOCK_SHIFT;
+}
+
+void time_init(void)
+{
+	sched_clock_multiplier = ((u64)NSEC_PER_SEC << SCHED_CLOCK_SHIFT) /
+		c6x_core_freq;
+
+	c6x_arch_init_clocksource();
+	c6x_arch_init_clockevents();
+}
+
diff --git a/arch/c6x/kernel/traps.c b/arch/c6x/kernel/traps.c
new file mode 100644
index 0000000..ddb78da
--- /dev/null
+++ b/arch/c6x/kernel/traps.c
@@ -0,0 +1,416 @@
+/*
+ *  linux/arch/c6x/kernel/traps.c
+ *
+ *  Port on Texas Instruments TMS320C6x architecture
+ *
+ *  Copyright (C) 2004, 2006, 2009, 2010, 2011 Texas Instruments Incorporated
+ *  Author: Aurelien Jacquiot (aurelien.jacquiot@...una.com)
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ *
+ *  Sets up all exception vectors
+ */
+#include <linux/sched.h>
+#include <linux/signal.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/types.h>
+#include <linux/user.h>
+#include <linux/string.h>
+#include <linux/linkage.h>
+#include <linux/linkage.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/kallsyms.h>
+#include <linux/ptrace.h>
+#include <linux/bug.h>
+
+#include <asm/setup.h>
+#include <asm/system.h>
+#include <asm/segment.h>
+#include <asm/traps.h>
+#include <asm/pgtable.h>
+#include <linux/bitops.h>
+#include <asm/irq.h>
+
+void __init trap_init(void)
+{
+	ack_exception(EXCEPT_TYPE_NXF);
+	ack_exception(EXCEPT_TYPE_EXC);
+	ack_exception(EXCEPT_TYPE_IXF);
+	ack_exception(EXCEPT_TYPE_SXF);
+	enable_exception();
+}
+
+void dump_stack(void)
+{
+	unsigned long stack;
+
+	show_stack(current, &stack);
+}
+EXPORT_SYMBOL(dump_stack);
+
+
+void die(char *str, struct pt_regs *fp, int nr)
+{
+	console_verbose();
+	printk(KERN_ERR "%s: %08x\n", str, nr);
+	show_regs(fp);
+
+	if (*((unsigned long *) (PAGE_SIZE + (unsigned long) current))
+	    != STACK_MAGIC)
+		printk(KERN_ERR "Corrupted stack page\n");
+	printk(KERN_ERR "Process %s (pid: %d, stackpage=%08lx)\n",
+	       current->comm, current->pid, (PAGE_SIZE +
+					     (unsigned long) current));
+
+	dump_stack();
+	while (1)
+		;
+}
+
+static void die_if_kernel(char *str, struct pt_regs *fp, int nr)
+{
+	if (user_mode(fp))
+		return;
+
+	die(str, fp, nr);
+}
+
+
+/* Internal exceptions */
+static struct exception_info iexcept_table[10] = {
+	{ "Oops - instruction fetch", SIGBUS, BUS_ADRERR },
+	{ "Oops - fetch packet", SIGBUS, BUS_ADRERR },
+	{ "Oops - execute packet", SIGILL, ILL_ILLOPC },
+	{ "Oops - undefined instruction", SIGILL, ILL_ILLOPC },
+	{ "Oops - resource conflict", SIGILL, ILL_ILLOPC },
+	{ "Oops - resource access", SIGILL, ILL_PRVREG },
+	{ "Oops - privilege", SIGILL, ILL_PRVOPC },
+	{ "Oops - loops buffer", SIGILL, ILL_ILLOPC },
+	{ "Oops - software exception", SIGILL, ILL_ILLTRP },
+	{ "Oops - unknown exception", SIGILL, ILL_ILLOPC }
+};
+
+/* External exceptions */
+static struct exception_info eexcept_table[128] = {
+	{ "Oops - external exception", SIGBUS, BUS_ADRERR },
+	{ "Oops - external exception", SIGBUS, BUS_ADRERR },
+	{ "Oops - external exception", SIGBUS, BUS_ADRERR },
+	{ "Oops - external exception", SIGBUS, BUS_ADRERR },
+	{ "Oops - external exception", SIGBUS, BUS_ADRERR },
+	{ "Oops - external exception", SIGBUS, BUS_ADRERR },
+	{ "Oops - external exception", SIGBUS, BUS_ADRERR },
+	{ "Oops - external exception", SIGBUS, BUS_ADRERR },
+	{ "Oops - external exception", SIGBUS, BUS_ADRERR },
+	{ "Oops - external exception", SIGBUS, BUS_ADRERR },
+	{ "Oops - external exception", SIGBUS, BUS_ADRERR },
+	{ "Oops - external exception", SIGBUS, BUS_ADRERR },
+	{ "Oops - external exception", SIGBUS, BUS_ADRERR },
+	{ "Oops - external exception", SIGBUS, BUS_ADRERR },
+	{ "Oops - external exception", SIGBUS, BUS_ADRERR },
+	{ "Oops - external exception", SIGBUS, BUS_ADRERR },
+	{ "Oops - external exception", SIGBUS, BUS_ADRERR },
+	{ "Oops - external exception", SIGBUS, BUS_ADRERR },
+	{ "Oops - external exception", SIGBUS, BUS_ADRERR },
+	{ "Oops - external exception", SIGBUS, BUS_ADRERR },
+	{ "Oops - external exception", SIGBUS, BUS_ADRERR },
+	{ "Oops - external exception", SIGBUS, BUS_ADRERR },
+	{ "Oops - external exception", SIGBUS, BUS_ADRERR },
+	{ "Oops - external exception", SIGBUS, BUS_ADRERR },
+	{ "Oops - external exception", SIGBUS, BUS_ADRERR },
+	{ "Oops - external exception", SIGBUS, BUS_ADRERR },
+	{ "Oops - external exception", SIGBUS, BUS_ADRERR },
+	{ "Oops - external exception", SIGBUS, BUS_ADRERR },
+	{ "Oops - external exception", SIGBUS, BUS_ADRERR },
+	{ "Oops - external exception", SIGBUS, BUS_ADRERR },
+	{ "Oops - external exception", SIGBUS, BUS_ADRERR },
+	{ "Oops - external exception", SIGBUS, BUS_ADRERR },
+
+	{ "Oops - external exception", SIGBUS, BUS_ADRERR },
+	{ "Oops - external exception", SIGBUS, BUS_ADRERR },
+	{ "Oops - external exception", SIGBUS, BUS_ADRERR },
+	{ "Oops - external exception", SIGBUS, BUS_ADRERR },
+	{ "Oops - external exception", SIGBUS, BUS_ADRERR },
+	{ "Oops - external exception", SIGBUS, BUS_ADRERR },
+	{ "Oops - external exception", SIGBUS, BUS_ADRERR },
+	{ "Oops - external exception", SIGBUS, BUS_ADRERR },
+	{ "Oops - external exception", SIGBUS, BUS_ADRERR },
+	{ "Oops - external exception", SIGBUS, BUS_ADRERR },
+	{ "Oops - external exception", SIGBUS, BUS_ADRERR },
+	{ "Oops - external exception", SIGBUS, BUS_ADRERR },
+	{ "Oops - external exception", SIGBUS, BUS_ADRERR },
+	{ "Oops - external exception", SIGBUS, BUS_ADRERR },
+	{ "Oops - external exception", SIGBUS, BUS_ADRERR },
+	{ "Oops - external exception", SIGBUS, BUS_ADRERR },
+	{ "Oops - external exception", SIGBUS, BUS_ADRERR },
+	{ "Oops - external exception", SIGBUS, BUS_ADRERR },
+	{ "Oops - external exception", SIGBUS, BUS_ADRERR },
+	{ "Oops - external exception", SIGBUS, BUS_ADRERR },
+	{ "Oops - external exception", SIGBUS, BUS_ADRERR },
+	{ "Oops - external exception", SIGBUS, BUS_ADRERR },
+	{ "Oops - external exception", SIGBUS, BUS_ADRERR },
+	{ "Oops - external exception", SIGBUS, BUS_ADRERR },
+	{ "Oops - external exception", SIGBUS, BUS_ADRERR },
+	{ "Oops - external exception", SIGBUS, BUS_ADRERR },
+	{ "Oops - external exception", SIGBUS, BUS_ADRERR },
+	{ "Oops - external exception", SIGBUS, BUS_ADRERR },
+	{ "Oops - external exception", SIGBUS, BUS_ADRERR },
+	{ "Oops - external exception", SIGBUS, BUS_ADRERR },
+	{ "Oops - external exception", SIGBUS, BUS_ADRERR },
+	{ "Oops - external exception", SIGBUS, BUS_ADRERR },
+
+	{ "Oops - external exception", SIGBUS, BUS_ADRERR },
+	{ "Oops - external exception", SIGBUS, BUS_ADRERR },
+	{ "Oops - external exception", SIGBUS, BUS_ADRERR },
+	{ "Oops - external exception", SIGBUS, BUS_ADRERR },
+	{ "Oops - external exception", SIGBUS, BUS_ADRERR },
+	{ "Oops - external exception", SIGBUS, BUS_ADRERR },
+	{ "Oops - external exception", SIGBUS, BUS_ADRERR },
+	{ "Oops - external exception", SIGBUS, BUS_ADRERR },
+	{ "Oops - external exception", SIGBUS, BUS_ADRERR },
+	{ "Oops - external exception", SIGBUS, BUS_ADRERR },
+	{ "Oops - external exception", SIGBUS, BUS_ADRERR },
+	{ "Oops - external exception", SIGBUS, BUS_ADRERR },
+	{ "Oops - external exception", SIGBUS, BUS_ADRERR },
+	{ "Oops - external exception", SIGBUS, BUS_ADRERR },
+	{ "Oops - external exception", SIGBUS, BUS_ADRERR },
+	{ "Oops - external exception", SIGBUS, BUS_ADRERR },
+	{ "Oops - external exception", SIGBUS, BUS_ADRERR },
+	{ "Oops - external exception", SIGBUS, BUS_ADRERR },
+	{ "Oops - external exception", SIGBUS, BUS_ADRERR },
+	{ "Oops - external exception", SIGBUS, BUS_ADRERR },
+	{ "Oops - external exception", SIGBUS, BUS_ADRERR },
+	{ "Oops - external exception", SIGBUS, BUS_ADRERR },
+	{ "Oops - external exception", SIGBUS, BUS_ADRERR },
+	{ "Oops - external exception", SIGBUS, BUS_ADRERR },
+	{ "Oops - external exception", SIGBUS, BUS_ADRERR },
+	{ "Oops - external exception", SIGBUS, BUS_ADRERR },
+	{ "Oops - external exception", SIGBUS, BUS_ADRERR },
+	{ "Oops - external exception", SIGBUS, BUS_ADRERR },
+	{ "Oops - external exception", SIGBUS, BUS_ADRERR },
+	{ "Oops - external exception", SIGBUS, BUS_ADRERR },
+	{ "Oops - external exception", SIGBUS, BUS_ADRERR },
+	{ "Oops - external exception", SIGBUS, BUS_ADRERR },
+
+	{ "Oops - external exception", SIGBUS, BUS_ADRERR },
+	{ "Oops - external exception", SIGBUS, BUS_ADRERR },
+	{ "Oops - external exception", SIGBUS, BUS_ADRERR },
+	{ "Oops - external exception", SIGBUS, BUS_ADRERR },
+	{ "Oops - external exception", SIGBUS, BUS_ADRERR },
+	{ "Oops - external exception", SIGBUS, BUS_ADRERR },
+	{ "Oops - external exception", SIGBUS, BUS_ADRERR },
+	{ "Oops - external exception", SIGBUS, BUS_ADRERR },
+	{ "Oops - external exception", SIGBUS, BUS_ADRERR },
+	{ "Oops - external exception", SIGBUS, BUS_ADRERR },
+	{ "Oops - external exception", SIGBUS, BUS_ADRERR },
+	{ "Oops - external exception", SIGBUS, BUS_ADRERR },
+	{ "Oops - external exception", SIGBUS, BUS_ADRERR },
+	{ "Oops - external exception", SIGBUS, BUS_ADRERR },
+	{ "Oops - external exception", SIGBUS, BUS_ADRERR },
+	{ "Oops - external exception", SIGBUS, BUS_ADRERR },
+	{ "Oops - external exception", SIGBUS, BUS_ADRERR },
+	{ "Oops - external exception", SIGBUS, BUS_ADRERR },
+	{ "Oops - external exception", SIGBUS, BUS_ADRERR },
+	{ "Oops - external exception", SIGBUS, BUS_ADRERR },
+	{ "Oops - external exception", SIGBUS, BUS_ADRERR },
+	{ "Oops - external exception", SIGBUS, BUS_ADRERR },
+	{ "Oops - external exception", SIGBUS, BUS_ADRERR },
+	{ "Oops - CPU memory protection fault", SIGSEGV, SEGV_ACCERR },
+	{ "Oops - CPU memory protection fault in L1P", SIGSEGV, SEGV_ACCERR },
+	{ "Oops - DMA memory protection fault in L1P", SIGSEGV, SEGV_ACCERR },
+	{ "Oops - CPU memory protection fault in L1D", SIGSEGV, SEGV_ACCERR },
+	{ "Oops - DMA memory protection fault in L1D", SIGSEGV, SEGV_ACCERR },
+	{ "Oops - CPU memory protection fault in L2", SIGSEGV, SEGV_ACCERR },
+	{ "Oops - DMA memory protection fault in L2", SIGSEGV, SEGV_ACCERR },
+	{ "Oops - EMC CPU memory protection fault", SIGSEGV, SEGV_ACCERR },
+	{ "Oops - EMC bus error", SIGBUS, BUS_ADRERR }
+};
+
+static void do_trap(struct exception_info *except_info, struct pt_regs *regs)
+{
+	unsigned long addr = instruction_pointer(regs);
+	siginfo_t info;
+
+	if (except_info->code != TRAP_BRKPT)
+		printk(KERN_DEBUG "TRAP: %s PC[0x%lx] signo[%d] code[%d]\n",
+		       except_info->kernel_str, regs->pc,
+		       except_info->signo, except_info->code);
+
+	die_if_kernel(except_info->kernel_str, regs, addr);
+
+	info.si_signo = except_info->signo;
+	info.si_errno = 0;
+	info.si_code  = except_info->code;
+	info.si_addr  = (void __user *)addr;
+
+	force_sig_info(except_info->signo, &info, current);
+}
+
+/*
+ * Process an internal exception (non maskable)
+ */
+static int process_iexcept(struct pt_regs *regs)
+{
+	unsigned int iexcept_report = get_iexcept();
+	unsigned int iexcept_num;
+
+	ack_exception(EXCEPT_TYPE_IXF);
+
+	printk(KERN_ERR "IEXCEPT: PC[0x%lx]\n", regs->pc);
+
+	while (iexcept_report) {
+		iexcept_num = __ffs(iexcept_report);
+		iexcept_report &= ~(1 << iexcept_num);
+		set_iexcept(iexcept_report);
+		if (*(unsigned int *)regs->pc == BKPT_OPCODE) {
+			/* This is a breakpoint */
+			struct exception_info bkpt_exception = {
+				"Oops - undefined instruction",
+				  SIGTRAP, TRAP_BRKPT
+			};
+			do_trap(&bkpt_exception, regs);
+			iexcept_report &= ~(0xFF);
+			set_iexcept(iexcept_report);
+			continue;
+		}
+
+		do_trap(&iexcept_table[iexcept_num], regs);
+	}
+	return 0;
+}
+
+/*
+ * Process an external exception (maskable)
+ */
+static void process_eexcept(struct pt_regs *regs)
+{
+	unsigned int eexcept_num;
+	unsigned int bank = 0;
+	int i;
+
+	printk(KERN_ERR "EEXCEPT: PC[0x%lx]\n", regs->pc);
+
+	for (i = 0; i <= 3; i++) {
+		while (IC_MEXPMASK[i]) {
+			__dint();
+			eexcept_num = __ffs(IC_MEXPMASK[i]);
+			IC_MEXPMASK[i] &= ~(1 << eexcept_num); /* ack the external exception */
+			__rint();
+			do_trap(&eexcept_table[eexcept_num +
+					       (bank << 5)], regs);
+		}
+		bank++;
+	}
+
+	ack_exception(EXCEPT_TYPE_EXC);
+}
+
+void (*mach_nmi_handler)(struct pt_regs *regs);
+
+/*
+ * Main exception processing
+ */
+asmlinkage int process_exception(struct pt_regs *regs)
+{
+	unsigned int type;
+	unsigned int type_num;
+	unsigned int ie_num = 9; /* default is unknown exception */
+
+	while ((type = get_except_type()) != 0) {
+		type_num = fls(type) - 1;
+
+		switch (type_num) {
+		case EXCEPT_TYPE_NXF:
+			ack_exception(EXCEPT_TYPE_NXF);
+			die("Oops - NMI detected", regs,
+			    instruction_pointer(regs));
+			break;
+
+		case EXCEPT_TYPE_IXF:
+			if (process_iexcept(regs))
+				return 1;
+			break;
+
+		case EXCEPT_TYPE_EXC:
+			process_eexcept(regs);
+			break;
+
+		case EXCEPT_TYPE_SXF:
+			ie_num = 8;
+		default:
+			ack_exception(type_num);
+			do_trap(&iexcept_table[ie_num], regs);
+			break;
+		}
+	}
+	return 0;
+}
+
+static int kstack_depth_to_print = 48;
+
+static void show_trace(unsigned long *stack, unsigned long *endstack)
+{
+	unsigned long addr;
+	int i;
+
+	printk(KERN_DEBUG "Call trace:");
+	i = 0;
+	while (stack + 1 <= endstack) {
+		addr = *stack++;
+		/*
+		 * If the address is either in the text segment of the
+		 * kernel, or in the region which contains vmalloc'ed
+		 * memory, it *may* be the address of a calling
+		 * routine; if so, print it so that someone tracing
+		 * down the cause of the crash will be able to figure
+		 * out the call path that was taken.
+		 */
+		if (__kernel_text_address(addr)) {
+#ifndef CONFIG_KALLSYMS
+			if (i % 5 == 0)
+				printk(KERN_DEBUG "\n	    ");
+#endif
+			printk(KERN_DEBUG " [<%08lx>]", addr);
+			print_symbol(" %s\n", addr);
+			i++;
+		}
+	}
+	printk(KERN_DEBUG "\n");
+}
+
+void show_stack(struct task_struct *task, unsigned long *stack)
+{
+	unsigned long *p, *endstack;
+	int i;
+
+	if (!stack) {
+		if (task && task != current)
+			/* We know this is a kernel stack,
+			   so this is the start/end */
+			stack = (unsigned long *)thread_saved_ksp(task);
+		else
+			stack = (unsigned long *)&stack;
+	}
+	endstack = (unsigned long *)(((unsigned long)stack + THREAD_SIZE - 1)
+				     & -THREAD_SIZE);
+
+	printk(KERN_DEBUG "Stack from %08lx:", (unsigned long)stack);
+	for (i = 0, p = stack; i < kstack_depth_to_print; i++) {
+		if (p + 1 > endstack)
+			break;
+		if (i % 8 == 0)
+			printk(KERN_CONT "\n	    ");
+		printk(KERN_CONT " %08lx", *p++);
+	}
+	printk(KERN_CONT "\n");
+	show_trace(stack, endstack);
+}
+
+int is_valid_bugaddr(unsigned long addr)
+{
+	return __kernel_text_address(addr);
+}
+
diff --git a/arch/c6x/kernel/vectors.S b/arch/c6x/kernel/vectors.S
new file mode 100644
index 0000000..8e65550
--- /dev/null
+++ b/arch/c6x/kernel/vectors.S
@@ -0,0 +1,81 @@
+;
+;  linux/arch/c6x/kernel/vector.s
+;
+;  Port on Texas Instruments TMS320C6x architecture
+;
+;  Copyright (C) 2004, 2006, 2009, 2010, 2011 Texas Instruments Incorporated
+;  Author: Aurelien Jacquiot (aurelien.jacquiot@...una.com)
+;
+;  This program is free software; you can redistribute it and/or modify
+;  it under the terms of the GNU General Public License version 2 as
+;  published by the Free Software Foundation.
+;
+;  This section handles all the interrupt vector routines.
+;  At RESET the processor sets up the DRAM timing parameters and
+;  branches to the label _c_int00 which handles initialization for the C code.
+;
+
+#define ALIGNMENT 5
+
+#ifdef CONFIG_BIG_KERNEL
+	.macro IRQVEC name, handler
+	.align ALIGNMENT
+	.global \name
+\name:	STW	.D2T1	A0,*B15--[2]
+ ||	MVKL	.S1	\handler,A0
+	MVKH	.S1	\handler,A0
+	B	.S2X	A0
+	LDW	.D2T1	*++B15[2],A0
+	NOP	4
+	NOP
+	NOP
+	.endm
+#else /* CONFIG_BIG_KERNEL */
+	.macro IRQVEC name, handler
+	.align ALIGNMENT
+	.global \name
+\name:	B	.S2	\handler
+	NOP
+	NOP
+	NOP
+	NOP
+	NOP
+	NOP
+	NOP
+	.endm
+#endif /* CONFIG_BIG_KERNEL */
+
+	   .sect ".vectors","ax"
+	   .align ALIGNMENT
+#ifdef CONFIG_BIG_KERNEL
+RESET:	   MVKL	.S1	_c_int00,A0		; branch to _c_int00
+	   MVKH	.S1	_c_int00,A0
+	   B	.S2X	A0
+#else
+RESET:	   B	.S2	_c_int00
+	   NOP
+	   NOP
+#endif
+	   NOP
+	   NOP
+	   NOP
+	   NOP
+	   NOP
+
+
+	   IRQVEC NMI,_nmi_handler		; NMI interrupt
+	   IRQVEC AINT,_bad_interrupt		; reserved
+	   IRQVEC MSGINT,_bad_interrupt		; reserved
+
+	   IRQVEC INT4,_int4_handler
+	   IRQVEC INT5,_int5_handler
+	   IRQVEC INT6,_int6_handler
+	   IRQVEC INT7,_int7_handler
+	   IRQVEC INT8,_int8_handler
+	   IRQVEC INT9,_int9_handler
+	   IRQVEC INT10,_int10_handler
+	   IRQVEC INT11,_int11_handler
+	   IRQVEC INT12,_int12_handler
+	   IRQVEC INT13,_int13_handler
+	   IRQVEC INT14,_int14_handler
+	   IRQVEC INT15,_int15_handler
diff --git a/arch/c6x/kernel/vmlinux.lds.S b/arch/c6x/kernel/vmlinux.lds.S
new file mode 100644
index 0000000..10e6177
--- /dev/null
+++ b/arch/c6x/kernel/vmlinux.lds.S
@@ -0,0 +1,205 @@
+/*
+ * ld script for the c6x kernel
+ *
+ *  Copyright (C) 2010, 2011 Texas Instruments Incorporated
+ *  Mark Salter <msalter@...hat.com>
+ */
+#define __VMLINUX_LDS__
+#include <asm-generic/vmlinux.lds.h>
+#include <asm/thread_info.h>
+#include <asm/page.h>
+#include <mach/board.h>
+
+
+ENTRY(_c_int00)
+
+#ifdef CONFIG_CPU_BIG_ENDIAN
+jiffies = jiffies_64 + 4;
+#else
+jiffies = jiffies_64;
+#endif
+
+SECTIONS
+{
+#ifdef CONFIG_XIP_KERNEL
+	. = CONFIG_XIP_KERNEL_TEXT_ADDR;
+#else
+	. = PAGE_OFFSET;
+#endif
+
+	.vectors :
+	{
+		VMLINUX_SYMBOL(_vectors_start) = .;
+		*(.vectors)
+		VMLINUX_SYMBOL(_vectors_end) = .;
+	}
+
+#ifdef CONFIG_XIP_KERNEL
+	. = CONFIG_XIP_KERNEL_TEXT_ADDR + 0x400;
+#else
+	. = PAGE_OFFSET + 0x400;
+#endif
+	. = ALIGN(0x1000);
+	.cmdline : { *(.cmdline) }
+
+	/* read-only */
+	.text :
+	{
+		VMLINUX_SYMBOL(_stext) = .;
+		VMLINUX_SYMBOL(_text) = .;
+		TEXT_TEXT
+		SCHED_TEXT
+		LOCK_TEXT
+		IRQENTRY_TEXT
+		KPROBES_TEXT
+#if defined(CONFIG_XIP_KERNEL) || !defined(CONFIG_BIG_KERNEL)
+		VMLINUX_SYMBOL(_sinittext) = .;
+		INIT_TEXT
+		VMLINUX_SYMBOL(_einittext) = .;
+		EXIT_TEXT
+#endif
+		*(.fixup)
+		*(.gnu.warning)
+	}
+
+	EXCEPTION_TABLE(16)
+	NOTES
+
+	RO_DATA_SECTION(32)
+	.rodata_c6x :
+	{
+		*(.const)
+		*(.switch)
+	}
+	. = ALIGN(8);
+	.dynamic :
+	{
+		*(.dynamic)
+	}
+	. = ALIGN(128);
+	VMLINUX_SYMBOL(_rodata_end) = .;
+
+	VMLINUX_SYMBOL(_etext) = .;
+
+#ifdef CONFIG_XIP_KERNEL
+	. = PAGE_OFFSET;
+	.bss : AT(VMLINUX_SYMBOL(_rodata_end))
+#else
+	.bss :
+#endif
+	{
+		VMLINUX_SYMBOL(__bss_start) = .;
+		*(.bss .bss.*)
+		*(COMMON)
+		*(.far)
+		. = ALIGN(128);
+		VMLINUX_SYMBOL(__bss_stop) = .;
+		VMLINUX_SYMBOL(__bss_stop) = .;
+	}
+
+#ifdef CONFIG_XIP_KERNEL
+	.data : AT(LOADADDR(.bss) + SIZEOF(.bss))
+#else
+	.data :
+#endif
+	{
+		VMLINUX_SYMBOL(_sdata) = .;
+		INIT_TASK_DATA(THREAD_SIZE)
+		NOSAVE_DATA
+		PAGE_ALIGNED_DATA(PAGE_SIZE)
+		CACHELINE_ALIGNED_DATA(128)
+		READ_MOSTLY_DATA(128)
+		DATA_DATA
+		CONSTRUCTORS
+		*(.data1)
+		*(.fardata .fardata.*)
+		. = ALIGN(8);
+	}
+#ifdef CONFIG_XIP_KERNEL
+	.neardata : AT(LOADADDR(.data) + SIZEOF(.data))
+#else
+	.neardata :
+#endif
+	{
+		*(.neardata .neardata.* .gnu.linkonce.s.*)
+#ifdef CONFIG_XIP_KERNEL
+		/* The init section should be last, so when we free it, it goes into
+		 * the general memory pool, and (hopefully) will decrease fragmentation
+		 * a tiny bit. The init section has a _requirement_ that it be
+		 * PAGE_SIZE aligned
+		 */
+		. = ALIGN(PAGE_SIZE);
+#endif
+	}
+
+	VMLINUX_SYMBOL(_edata) = .;
+	VMLINUX_SYMBOL(_data_lma) = LOADADDR(.data);
+
+	VMLINUX_SYMBOL(__init_begin) = .;
+
+#ifndef CONFIG_XIP_KERNEL
+#ifdef CONFIG_BIG_KERNEL
+	INIT_TEXT_SECTION(PAGE_SIZE)
+
+	/* We have to discard exit text and such at runtime, not link time, to
+	 * handle embedded cross-section references (alt instructions, bug
+	 * table, eh_frame, etc...).  We need all of our .text up front and
+	 * .data after it for PCREL call issues.
+	 */
+	.exit.text :
+	{
+		EXIT_TEXT
+	}
+	. = ALIGN(16);
+#endif
+	INIT_DATA_SECTION(16)
+	PERCPU(128,PAGE_SIZE)
+
+	.exit.data :
+	{
+		EXIT_DATA
+	}
+#else
+	.init.data : AT(LOADADDR(.neardata) + SIZEOF(.neardata))
+	{
+		VMLINUX_SYMBOL(_sinitdata) = .;
+		INIT_DATA
+		INIT_SETUP(16)
+		INIT_CALLS
+		CON_INITCALL
+		SECURITY_INITCALL
+		INIT_RAM_FS
+		. = ALIGN(8);
+		VMLINUX_SYMBOL(__per_cpu_load) = .;
+		VMLINUX_SYMBOL(__per_cpu_start) = .;
+		*(.data.percpu.first)
+		*(.data.percpu.page_aligned)
+		*(.data.percpu)
+		*(.data.percpu.shared_aligned)
+		VMLINUX_SYMBOL(__per_cpu_end) = .;
+
+		EXIT_DATA
+
+		. = ALIGN(8);
+	}
+#endif
+	. = ALIGN(PAGE_SIZE);
+
+	VMLINUX_SYMBOL(__init_end) = .;
+
+	/*
+	 * _ebss is used solely for CONFIG_MTD_UCLINUX support.
+	 * Traditionally, _ebss (end of .bss) would be the end of a kernel
+	 * image where a ROMFS could be appended. In this case, .bss is
+	 * elsewhere but we define _ebss at the end.
+	 */
+	VMLINUX_SYMBOL(_ebss) = .;
+
+	VMLINUX_SYMBOL(_end) = . ;
+
+	STABS_DEBUG
+
+	DWARF_DEBUG
+
+	DISCARDS
+}
-- 
1.6.2.5

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ