#include <linux/hw_breakpoint.h>
#include <linux/cpuidle.h>
#include <linux/leds.h>
+#include <linux/console.h>
+#include <linux/mtk_ram_console.h>
#include <asm/cacheflush.h>
#include <asm/idmap.h>
#include <asm/thread_notify.h>
#include <asm/stacktrace.h>
#include <asm/mach/time.h>
+#include <mach/system.h>
#ifdef CONFIG_CC_STACKPROTECTOR
#include <linux/stackprotector.h>
"ARM" , "Thumb" , "Jazelle", "ThumbEE"
};
+#ifdef CONFIG_SMP
+void arch_trigger_all_cpu_backtrace(void)
+{
+ smp_send_all_cpu_backtrace();
+}
+#else
+void arch_trigger_all_cpu_backtrace(void)
+{
+ dump_stack();
+}
+#endif
+
extern void call_with_stack(void (*fn)(void *), void *arg, void *sp);
typedef void (*phys_reset_t)(unsigned long);
+#ifdef CONFIG_ARM_FLUSH_CONSOLE_ON_RESTART
+void arm_machine_flush_console(void)
+{
+ printk("\n");
+ pr_emerg("Restarting %s\n", linux_banner);
+ if (console_trylock()) {
+ console_unlock();
+ return;
+ }
+
+ mdelay(50);
+
+ local_irq_disable();
+ if (!console_trylock())
+ pr_emerg("arm_restart: Console was locked! Busting\n");
+ else
+ pr_emerg("arm_restart: Console was locked!\n");
+ console_unlock();
+}
+#else
+void arm_machine_flush_console(void)
+{
+}
+#endif
+
/*
* A temporary stack to use for CPU reset. This is static so that we
* don't clobber it with the identity mapping. When running with this
*/
static u64 soft_restart_stack[16];
+void arm_machine_restart(char mode, const char *cmd)
+{
+ /* Flush the console to make sure all the relevant messages make it
+ * out to the console drivers */
+ arm_machine_flush_console();
+
+ /* Disable interrupts first */
+ local_irq_disable();
+ local_fiq_disable();
+
+ /*
+ * Tell the mm system that we are going to reboot -
+ * we may need it to insert some 1:1 mappings so that
+ * soft boot works.
+ */
+ setup_mm_for_reboot();
+
+ /* When l1 is disabled and l2 is enabled, the spinlock cannot get the lock,
+ * so we need to disable the l2 as well. by Chia-Hao Hsu
+ */
+ outer_flush_all();
+ outer_disable();
+ outer_flush_all();
+
+ /* Clean and invalidate caches */
+ flush_cache_all();
+#ifdef CONFIG_RESTART_DISABLE_CACHE
+ /* Turn off caching */
+ // cpu_proc_fin(); // Don't turn off cach during reboot phase. CA15 have risk if turn off cach.
+#endif
+ /* Push out any further dirty data, and ensure cache is empty */
+ flush_cache_all();
+
+ /*
+ * Now call the architecture specific reboot code.
+ */
+ arch_reset(mode, cmd);
+
+ /*
+ * Whoops - the architecture was unable to reboot.
+ * Tell the user!
+ */
+ mdelay(1000);
+ printk("Reboot failed -- System halted\n");
+ while (1);
+}
+
static void __soft_restart(void *addr)
{
phys_reset_t phys_reset;
local_fiq_disable();
/* Disable the L2 if we're the last man standing. */
- if (num_online_cpus() == 1)
+ if (num_online_cpus() == 1) {
+ outer_flush_all();
outer_disable();
+ }
/* Change to the new stack and continue with the reset. */
call_with_stack(__soft_restart, (void *)addr, (void *)stack);
void arch_cpu_idle_enter(void)
{
+ idle_notifier_call_chain(IDLE_START);
ledtrig_cpu(CPU_LED_IDLE_START);
#ifdef CONFIG_PL310_ERRATA_769419
wmb();
void arch_cpu_idle_exit(void)
{
ledtrig_cpu(CPU_LED_IDLE_END);
+ idle_notifier_call_chain(IDLE_END);
}
#ifdef CONFIG_HOTPLUG_CPU
*/
void machine_shutdown(void)
{
+#ifdef CONFIG_SMP
+ /*
+ * Disable preemption so we're guaranteed to
+ * run to power off or reboot and prevent
+ * the possibility of switching to another
+ * thread that might wind up blocking on
+ * one of the stopped CPUs.
+ */
+ printk("machine_shutdown: start, Proess(%s:%d)\n", current->comm, current->pid);
+ dump_stack();
+ preempt_disable();
+#endif
disable_nonboot_cpus();
+ printk("machine_shutdown: done\n");
}
/*
while (1);
}
+extern int reboot_pid;
/*
* Power-off simply requires that the secondary CPUs stop performing any
* activity (executing tasks, handling interrupts). smp_send_stop()
*/
void machine_power_off(void)
{
- smp_send_stop();
+ struct task_struct *tsk;
+
+ /* Disable interrupts first */
+ local_irq_disable();
+ local_fiq_disable();
+
+ smp_send_stop();
+ if(reboot_pid > 1)
+ {
+ tsk = find_task_by_vpid(reboot_pid);
+ if(tsk == NULL)
+ tsk = current;
+ dump_stack();
+ }
+ else
+ {
+ tsk = current;
+ }
+
+ if(tsk->real_parent)
+ {
+ if(tsk->real_parent->real_parent)
+ {
+ printk("machine_shutdown: start, Proess(%s:%d). father %s:%d. grandfather %s:%d.\n",
+ tsk->comm, tsk->pid,tsk->real_parent->comm,tsk->real_parent->pid,
+ tsk->real_parent->real_parent->comm,tsk->real_parent->real_parent->pid);
+ }
+ else
+ {
+ printk("machine_shutdown: start, Proess(%s:%d). father %s:%d.\n",
+ tsk->comm, tsk->pid,tsk->real_parent->comm,tsk->real_parent->pid);
+ }
+ }
+ else
+ {
+ printk("machine_shutdown: start, Proess(%s:%d)\n", tsk->comm, tsk->pid);
+ }
+
+#ifdef CONFIG_MTK_EMMC_SUPPORT
+ last_kmsg_store_to_emmc();
+#endif
if (pm_power_off)
pm_power_off();
*/
void machine_restart(char *cmd)
{
+ struct task_struct *tsk;
+ /* Disable interrupts first */
+ local_irq_disable();
+ local_fiq_disable();
+
smp_send_stop();
+ if(reboot_pid > 1)
+ {
+ tsk = find_task_by_vpid(reboot_pid);
+ if(tsk == NULL)
+ tsk = current;
+ dump_stack();
+ }
+ else
+ {
+ tsk = current;
+ }
+
+ if(tsk->real_parent)
+ {
+ if(tsk->real_parent->real_parent)
+ {
+ printk("machine_shutdown: start, Proess(%s:%d). father %s:%d. grandfather %s:%d.\n",
+ tsk->comm, tsk->pid,tsk->real_parent->comm,tsk->real_parent->pid,
+ tsk->real_parent->real_parent->comm,tsk->real_parent->real_parent->pid);
+ }
+ else
+ {
+ printk("machine_shutdown: start, Proess(%s:%d). father %s:%d.\n",
+ tsk->comm, tsk->pid,tsk->real_parent->comm,tsk->real_parent->pid);
+ }
+ }
+ else
+ {
+ printk("machine_shutdown: start, Proess(%s:%d)\n", tsk->comm, tsk->pid);
+ }
+
+ /* Flush the console to make sure all the relevant messages make it
+ * out to the console drivers */
+ arm_machine_flush_console();
+
arm_pm_restart(reboot_mode, cmd);
/* Give a grace period for failure to restart of 1s */
while (1);
}
+/*
+ * dump a block of kernel memory from around the given address
+ */
+static void show_data(unsigned long addr, int nbytes, const char *name)
+{
+ int i, j;
+ int nlines;
+ u32 *p;
+
+ /*
+ * don't attempt to dump non-kernel addresses or
+ * values that are probably just small negative numbers
+ */
+ if (addr < PAGE_OFFSET || addr > -256UL)
+ return;
+
+ printk("\n%s: %#lx:\n", name, addr);
+
+ /*
+ * round address down to a 32 bit boundary
+ * and always dump a multiple of 32 bytes
+ */
+ p = (u32 *)(addr & ~(sizeof(u32) - 1));
+ nbytes += (addr & (sizeof(u32) - 1));
+ nlines = (nbytes + 31) / 32;
+
+
+ for (i = 0; i < nlines; i++) {
+ /*
+ * just display low 16 bits of address to keep
+ * each line of the dump < 80 characters
+ */
+ printk("%04lx ", (unsigned long)p & 0xffff);
+ for (j = 0; j < 8; j++) {
+ u32 data;
+ if (probe_kernel_address(p, data)) {
+ printk(" ********");
+ } else {
+ printk(" %08x", data);
+ }
+ ++p;
+ }
+ printk("\n");
+ }
+}
+
+static void show_extra_register_data(struct pt_regs *regs, int nbytes)
+{
+ mm_segment_t fs;
+
+ fs = get_fs();
+ set_fs(KERNEL_DS);
+ show_data(regs->ARM_pc - nbytes, nbytes * 2, "PC");
+ show_data(regs->ARM_lr - nbytes, nbytes * 2, "LR");
+ show_data(regs->ARM_sp - nbytes, nbytes * 2, "SP");
+ show_data(regs->ARM_ip - nbytes, nbytes * 2, "IP");
+ show_data(regs->ARM_fp - nbytes, nbytes * 2, "FP");
+ show_data(regs->ARM_r0 - nbytes, nbytes * 2, "R0");
+ show_data(regs->ARM_r1 - nbytes, nbytes * 2, "R1");
+ show_data(regs->ARM_r2 - nbytes, nbytes * 2, "R2");
+ show_data(regs->ARM_r3 - nbytes, nbytes * 2, "R3");
+ show_data(regs->ARM_r4 - nbytes, nbytes * 2, "R4");
+ show_data(regs->ARM_r5 - nbytes, nbytes * 2, "R5");
+ show_data(regs->ARM_r6 - nbytes, nbytes * 2, "R6");
+ show_data(regs->ARM_r7 - nbytes, nbytes * 2, "R7");
+ show_data(regs->ARM_r8 - nbytes, nbytes * 2, "R8");
+ show_data(regs->ARM_r9 - nbytes, nbytes * 2, "R9");
+ show_data(regs->ARM_r10 - nbytes, nbytes * 2, "R10");
+ set_fs(fs);
+}
+
void __show_regs(struct pt_regs *regs)
{
unsigned long flags;
printk("Control: %08x%s\n", ctrl, buf);
}
#endif
+
+ show_extra_register_data(regs, 128);
}
void show_regs(struct pt_regs * regs)