This represents a rollup of a series of reverts, simplified are modifications to remove fiq_glue and fiq_debugger references in: arch/arm/common/Kconfig arch/arm/common/Makefile drivers/staging/android/Kconfig drivers/staging/android/Makefile And deletion of: arch/arm/common/fiq_glue.S arch/arm/common/fiq_glue_setup.c drivers/staging/android/fiq_debugger/ The reverts specific to android-4.14 are as follows: Revert "ANDROID: fiq_debugger: Remove wakelock.h dependencies" This reverts committirimbinof9cbd12ed7
. Revert "ANDROID: fiq_debugger: Add fiq_debugger.disable option" This reverts commit76d292f95a
. Revert "ANDROID: fiq_debugger: Add option to apply uart overlay by FIQ_DEBUGGER_UART_OVERLAY" This reverts commit0ff9e291c1
. Revert "ANDROID: fiq_debugger: Add fiq_watchdog_triggered api" This reverts commit9c027e6c23
. Revert "ANDROID: fiq_debugger: Call fiq_debugger_printf through a function pointer from cpu specific code" This reverts commit9200a45dc9
. Revert "ANDROID: fiq_debugger: add ARM64 support" This reverts commitc9d6bc7ab0
. Revert "ANDROID: fiq_debugger: split arm support into fiq_debugger_arm.c" This reverts commitefffceb1e9
. Revert "ANDROID: fiq_debugger: use pt_regs for registers" This reverts commitbf32f8accc
. Revert "ANDROID: fiq_debugger: allow compiling without CONFIG_FIQ_GLUE" This reverts commit16c3248941
. Revert "ANDROID: fiq_debugger: rename debug->fiq_debugger" This reverts commitd241f1dfc9
. Revert "ANDROID: fiq_debugger: move into drivers/staging/android/fiq_debugger/" This reverts commit0dc1cccb4f
. Revert "ANDROID: ARM: fiq_debugger: Update tty code for 3.9" This reverts commit4b55137d5e
. Revert "ANDROID: ARM: fiq_debugger: lock between tty and console writes" This reverts commita8be462329
. Revert "ANDROID: ARM: fiq_debugger: add process context reboot command" This reverts commitcb5774b503
. Revert "ANDROID: ARM: fiq_debugger: fix multiple consoles and make it a preferred console" This reverts commitaecfa53f35
. Revert "ANDROID: ARM: fiq_debugger: add support for kgdb" This reverts commit992dbb2a9a
. Revert "ANDROID: ARM: fiq_debugger: add debug_putc" This reverts commit5d12c56f2a
. Revert "ANDROID: ARM: fiq_debugger: add support for reboot commands" This reverts commit14dbf8675b
. Revert "ANDROID: ARM: fiq_debugger: Add generic fiq serial debugger" This reverts commit05e1c7f617
. Revert "ANDROID: ARM: fiq_glue: Add custom fiq return handler api." This reverts commite329aaf322
. Revert "ANDROID: ARM: fiq_glue: Add fiq_glue" This reverts commit47fe2f8d76
. Signed-off-by: Mark Salyzyn <salyzyn@google.com> Bug: 32402555 Bug: 36101220 Change-Id: I3f74b1ff5e4971d619bcb37a911fed68fbb538d5
parent
54236917c6
commit
a9d0871a56
@ -1,118 +0,0 @@ |
||||
/* |
||||
* Copyright (C) 2008 Google, Inc. |
||||
* |
||||
* This software is licensed under the terms of the GNU General Public |
||||
* License version 2, as published by the Free Software Foundation, and |
||||
* may be copied, distributed, and modified under those terms. |
||||
* |
||||
* 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. |
||||
* |
||||
*/ |
||||
|
||||
#include <linux/linkage.h> |
||||
#include <asm/assembler.h> |
||||
|
||||
.text |
||||
|
||||
.global fiq_glue_end
|
||||
|
||||
/* fiq stack: r0-r15,cpsr,spsr of interrupted mode */ |
||||
|
||||
ENTRY(fiq_glue) |
||||
/* store pc, cpsr from previous mode, reserve space for spsr */ |
||||
mrs r12, spsr |
||||
sub lr, lr, #4 |
||||
subs r10, #1 |
||||
bne nested_fiq |
||||
|
||||
str r12, [sp, #-8]! |
||||
str lr, [sp, #-4]! |
||||
|
||||
/* store r8-r14 from previous mode */ |
||||
sub sp, sp, #(7 * 4) |
||||
stmia sp, {r8-r14}^ |
||||
nop |
||||
|
||||
/* store r0-r7 from previous mode */ |
||||
stmfd sp!, {r0-r7} |
||||
|
||||
/* setup func(data,regs) arguments */ |
||||
mov r0, r9 |
||||
mov r1, sp |
||||
mov r3, r8 |
||||
|
||||
mov r7, sp |
||||
|
||||
/* Get sp and lr from non-user modes */ |
||||
and r4, r12, #MODE_MASK |
||||
cmp r4, #USR_MODE |
||||
beq fiq_from_usr_mode |
||||
|
||||
mov r7, sp |
||||
orr r4, r4, #(PSR_I_BIT | PSR_F_BIT) |
||||
msr cpsr_c, r4 |
||||
str sp, [r7, #(4 * 13)] |
||||
str lr, [r7, #(4 * 14)] |
||||
mrs r5, spsr |
||||
str r5, [r7, #(4 * 17)] |
||||
|
||||
cmp r4, #(SVC_MODE | PSR_I_BIT | PSR_F_BIT) |
||||
/* use fiq stack if we reenter this mode */ |
||||
subne sp, r7, #(4 * 3) |
||||
|
||||
fiq_from_usr_mode: |
||||
msr cpsr_c, #(SVC_MODE | PSR_I_BIT | PSR_F_BIT) |
||||
mov r2, sp |
||||
sub sp, r7, #12 |
||||
stmfd sp!, {r2, ip, lr} |
||||
/* call func(data,regs) */ |
||||
blx r3 |
||||
ldmfd sp, {r2, ip, lr} |
||||
mov sp, r2 |
||||
|
||||
/* restore/discard saved state */ |
||||
cmp r4, #USR_MODE |
||||
beq fiq_from_usr_mode_exit |
||||
|
||||
msr cpsr_c, r4 |
||||
ldr sp, [r7, #(4 * 13)] |
||||
ldr lr, [r7, #(4 * 14)] |
||||
msr spsr_cxsf, r5 |
||||
|
||||
fiq_from_usr_mode_exit: |
||||
msr cpsr_c, #(FIQ_MODE | PSR_I_BIT | PSR_F_BIT) |
||||
|
||||
ldmfd sp!, {r0-r7} |
||||
ldr lr, [sp, #(4 * 7)] |
||||
ldr r12, [sp, #(4 * 8)] |
||||
add sp, sp, #(10 * 4) |
||||
exit_fiq: |
||||
msr spsr_cxsf, r12 |
||||
add r10, #1 |
||||
cmp r11, #0 |
||||
moveqs pc, lr |
||||
bx r11 /* jump to custom fiq return function */ |
||||
|
||||
nested_fiq: |
||||
orr r12, r12, #(PSR_F_BIT) |
||||
b exit_fiq |
||||
|
||||
fiq_glue_end: |
||||
|
||||
ENTRY(fiq_glue_setup) /* func, data, sp, smc call number */ |
||||
stmfd sp!, {r4} |
||||
mrs r4, cpsr |
||||
msr cpsr_c, #(FIQ_MODE | PSR_I_BIT | PSR_F_BIT) |
||||
movs r8, r0 |
||||
mov r9, r1 |
||||
mov sp, r2 |
||||
mov r11, r3 |
||||
moveq r10, #0 |
||||
movne r10, #1 |
||||
msr cpsr_c, r4 |
||||
ldmfd sp!, {r4} |
||||
bx lr |
||||
|
@ -1,147 +0,0 @@ |
||||
/*
|
||||
* Copyright (C) 2010 Google, Inc. |
||||
* |
||||
* This software is licensed under the terms of the GNU General Public |
||||
* License version 2, as published by the Free Software Foundation, and |
||||
* may be copied, distributed, and modified under those terms. |
||||
* |
||||
* 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. |
||||
*/ |
||||
|
||||
#include <linux/kernel.h> |
||||
#include <linux/percpu.h> |
||||
#include <linux/slab.h> |
||||
#include <asm/fiq.h> |
||||
#include <asm/fiq_glue.h> |
||||
|
||||
extern unsigned char fiq_glue, fiq_glue_end; |
||||
extern void fiq_glue_setup(void *func, void *data, void *sp, |
||||
fiq_return_handler_t fiq_return_handler); |
||||
|
||||
static struct fiq_handler fiq_debbuger_fiq_handler = { |
||||
.name = "fiq_glue", |
||||
}; |
||||
DEFINE_PER_CPU(void *, fiq_stack); |
||||
static struct fiq_glue_handler *current_handler; |
||||
static fiq_return_handler_t fiq_return_handler; |
||||
static DEFINE_MUTEX(fiq_glue_lock); |
||||
|
||||
static void fiq_glue_setup_helper(void *info) |
||||
{ |
||||
struct fiq_glue_handler *handler = info; |
||||
fiq_glue_setup(handler->fiq, handler, |
||||
__get_cpu_var(fiq_stack) + THREAD_START_SP, |
||||
fiq_return_handler); |
||||
} |
||||
|
||||
int fiq_glue_register_handler(struct fiq_glue_handler *handler) |
||||
{ |
||||
int ret; |
||||
int cpu; |
||||
|
||||
if (!handler || !handler->fiq) |
||||
return -EINVAL; |
||||
|
||||
mutex_lock(&fiq_glue_lock); |
||||
if (fiq_stack) { |
||||
ret = -EBUSY; |
||||
goto err_busy; |
||||
} |
||||
|
||||
for_each_possible_cpu(cpu) { |
||||
void *stack; |
||||
stack = (void *)__get_free_pages(GFP_KERNEL, THREAD_SIZE_ORDER); |
||||
if (WARN_ON(!stack)) { |
||||
ret = -ENOMEM; |
||||
goto err_alloc_fiq_stack; |
||||
} |
||||
per_cpu(fiq_stack, cpu) = stack; |
||||
} |
||||
|
||||
ret = claim_fiq(&fiq_debbuger_fiq_handler); |
||||
if (WARN_ON(ret)) |
||||
goto err_claim_fiq; |
||||
|
||||
current_handler = handler; |
||||
on_each_cpu(fiq_glue_setup_helper, handler, true); |
||||
set_fiq_handler(&fiq_glue, &fiq_glue_end - &fiq_glue); |
||||
|
||||
mutex_unlock(&fiq_glue_lock); |
||||
return 0; |
||||
|
||||
err_claim_fiq: |
||||
err_alloc_fiq_stack: |
||||
for_each_possible_cpu(cpu) { |
||||
__free_pages(per_cpu(fiq_stack, cpu), THREAD_SIZE_ORDER); |
||||
per_cpu(fiq_stack, cpu) = NULL; |
||||
} |
||||
err_busy: |
||||
mutex_unlock(&fiq_glue_lock); |
||||
return ret; |
||||
} |
||||
|
||||
static void fiq_glue_update_return_handler(void (*fiq_return)(void)) |
||||
{ |
||||
fiq_return_handler = fiq_return; |
||||
if (current_handler) |
||||
on_each_cpu(fiq_glue_setup_helper, current_handler, true); |
||||
} |
||||
|
||||
int fiq_glue_set_return_handler(void (*fiq_return)(void)) |
||||
{ |
||||
int ret; |
||||
|
||||
mutex_lock(&fiq_glue_lock); |
||||
if (fiq_return_handler) { |
||||
ret = -EBUSY; |
||||
goto err_busy; |
||||
} |
||||
fiq_glue_update_return_handler(fiq_return); |
||||
ret = 0; |
||||
err_busy: |
||||
mutex_unlock(&fiq_glue_lock); |
||||
|
||||
return ret; |
||||
} |
||||
EXPORT_SYMBOL(fiq_glue_set_return_handler); |
||||
|
||||
int fiq_glue_clear_return_handler(void (*fiq_return)(void)) |
||||
{ |
||||
int ret; |
||||
|
||||
mutex_lock(&fiq_glue_lock); |
||||
if (WARN_ON(fiq_return_handler != fiq_return)) { |
||||
ret = -EINVAL; |
||||
goto err_inval; |
||||
} |
||||
fiq_glue_update_return_handler(NULL); |
||||
ret = 0; |
||||
err_inval: |
||||
mutex_unlock(&fiq_glue_lock); |
||||
|
||||
return ret; |
||||
} |
||||
EXPORT_SYMBOL(fiq_glue_clear_return_handler); |
||||
|
||||
/**
|
||||
* fiq_glue_resume - Restore fiqs after suspend or low power idle states |
||||
* |
||||
* This must be called before calling local_fiq_enable after returning from a |
||||
* power state where the fiq mode registers were lost. If a driver provided |
||||
* a resume hook when it registered the handler it will be called. |
||||
*/ |
||||
|
||||
void fiq_glue_resume(void) |
||||
{ |
||||
if (!current_handler) |
||||
return; |
||||
fiq_glue_setup(current_handler->fiq, current_handler, |
||||
__get_cpu_var(fiq_stack) + THREAD_START_SP, |
||||
fiq_return_handler); |
||||
if (current_handler->resume) |
||||
current_handler->resume(current_handler); |
||||
} |
||||
|
@ -1,33 +0,0 @@ |
||||
/*
|
||||
* Copyright (C) 2010 Google, Inc. |
||||
* |
||||
* This software is licensed under the terms of the GNU General Public |
||||
* License version 2, as published by the Free Software Foundation, and |
||||
* may be copied, distributed, and modified under those terms. |
||||
* |
||||
* 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. |
||||
*/ |
||||
|
||||
#ifndef __ASM_FIQ_GLUE_H |
||||
#define __ASM_FIQ_GLUE_H |
||||
|
||||
struct fiq_glue_handler { |
||||
void (*fiq)(struct fiq_glue_handler *h, void *regs, void *svc_sp); |
||||
void (*resume)(struct fiq_glue_handler *h); |
||||
}; |
||||
typedef void (*fiq_return_handler_t)(void); |
||||
|
||||
int fiq_glue_register_handler(struct fiq_glue_handler *handler); |
||||
int fiq_glue_set_return_handler(fiq_return_handler_t fiq_return); |
||||
int fiq_glue_clear_return_handler(fiq_return_handler_t fiq_return); |
||||
|
||||
#ifdef CONFIG_FIQ_GLUE |
||||
void fiq_glue_resume(void); |
||||
#else |
||||
static inline void fiq_glue_resume(void) {} |
||||
#endif |
||||
|
||||
#endif |
@ -1,7 +1,6 @@ |
||||
ccflags-y += -I$(src) # needed for trace events
|
||||
|
||||
obj-y += ion/
|
||||
obj-$(CONFIG_FIQ_DEBUGGER) += fiq_debugger/
|
||||
|
||||
obj-$(CONFIG_ASHMEM) += ashmem.o
|
||||
obj-$(CONFIG_ANDROID_VSOC) += vsoc.o
|
||||
|
@ -1,58 +0,0 @@ |
||||
config FIQ_DEBUGGER |
||||
bool "FIQ Mode Serial Debugger" |
||||
default n |
||||
depends on ARM || ARM64 |
||||
help |
||||
The FIQ serial debugger can accept commands even when the |
||||
kernel is unresponsive due to being stuck with interrupts |
||||
disabled. |
||||
|
||||
config FIQ_DEBUGGER_NO_SLEEP |
||||
bool "Keep serial debugger active" |
||||
depends on FIQ_DEBUGGER |
||||
default n |
||||
help |
||||
Enables the serial debugger at boot. Passing |
||||
fiq_debugger.no_sleep on the kernel commandline will |
||||
override this config option. |
||||
|
||||
config FIQ_DEBUGGER_WAKEUP_IRQ_ALWAYS_ON |
||||
bool "Don't disable wakeup IRQ when debugger is active" |
||||
depends on FIQ_DEBUGGER |
||||
default n |
||||
help |
||||
Don't disable the wakeup irq when enabling the uart clock. This will |
||||
cause extra interrupts, but it makes the serial debugger usable with |
||||
on some MSM radio builds that ignore the uart clock request in power |
||||
collapse. |
||||
|
||||
config FIQ_DEBUGGER_CONSOLE |
||||
bool "Console on FIQ Serial Debugger port" |
||||
depends on FIQ_DEBUGGER |
||||
default n |
||||
help |
||||
Enables a console so that printk messages are displayed on |
||||
the debugger serial port as the occur. |
||||
|
||||
config FIQ_DEBUGGER_CONSOLE_DEFAULT_ENABLE |
||||
bool "Put the FIQ debugger into console mode by default" |
||||
depends on FIQ_DEBUGGER_CONSOLE |
||||
default n |
||||
help |
||||
If enabled, this puts the fiq debugger into console mode by default. |
||||
Otherwise, the fiq debugger will start out in debug mode. |
||||
|
||||
config FIQ_DEBUGGER_UART_OVERLAY |
||||
bool "Install uart DT overlay" |
||||
depends on FIQ_DEBUGGER |
||||
select OF_OVERLAY |
||||
default n |
||||
help |
||||
If enabled, fiq debugger is calling fiq_debugger_uart_overlay() |
||||
that will apply overlay uart_overlay@0 to disable proper uart. |
||||
|
||||
config FIQ_WATCHDOG |
||||
bool |
||||
select FIQ_DEBUGGER |
||||
select PSTORE_RAM |
||||
default n |
@ -1,4 +0,0 @@ |
||||
obj-y += fiq_debugger.o
|
||||
obj-$(CONFIG_ARM) += fiq_debugger_arm.o
|
||||
obj-$(CONFIG_ARM64) += fiq_debugger_arm64.o
|
||||
obj-$(CONFIG_FIQ_WATCHDOG) += fiq_watchdog.o
|
File diff suppressed because it is too large
Load Diff
@ -1,64 +0,0 @@ |
||||
/*
|
||||
* drivers/staging/android/fiq_debugger/fiq_debugger.h |
||||
* |
||||
* Copyright (C) 2010 Google, Inc. |
||||
* Author: Colin Cross <ccross@android.com> |
||||
* |
||||
* This software is licensed under the terms of the GNU General Public |
||||
* License version 2, as published by the Free Software Foundation, and |
||||
* may be copied, distributed, and modified under those terms. |
||||
* |
||||
* 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. |
||||
* |
||||
*/ |
||||
|
||||
#ifndef _ARCH_ARM_MACH_TEGRA_FIQ_DEBUGGER_H_ |
||||
#define _ARCH_ARM_MACH_TEGRA_FIQ_DEBUGGER_H_ |
||||
|
||||
#include <linux/serial_core.h> |
||||
|
||||
#define FIQ_DEBUGGER_NO_CHAR NO_POLL_CHAR |
||||
#define FIQ_DEBUGGER_BREAK 0x00ff0100 |
||||
|
||||
#define FIQ_DEBUGGER_FIQ_IRQ_NAME "fiq" |
||||
#define FIQ_DEBUGGER_SIGNAL_IRQ_NAME "signal" |
||||
#define FIQ_DEBUGGER_WAKEUP_IRQ_NAME "wakeup" |
||||
|
||||
/**
|
||||
* struct fiq_debugger_pdata - fiq debugger platform data |
||||
* @uart_resume: used to restore uart state right before enabling |
||||
* the fiq. |
||||
* @uart_enable: Do the work necessary to communicate with the uart |
||||
* hw (enable clocks, etc.). This must be ref-counted. |
||||
* @uart_disable: Do the work necessary to disable the uart hw |
||||
* (disable clocks, etc.). This must be ref-counted. |
||||
* @uart_dev_suspend: called during PM suspend, generally not needed |
||||
* for real fiq mode debugger. |
||||
* @uart_dev_resume: called during PM resume, generally not needed |
||||
* for real fiq mode debugger. |
||||
*/ |
||||
struct fiq_debugger_pdata { |
||||
int (*uart_init)(struct platform_device *pdev); |
||||
void (*uart_free)(struct platform_device *pdev); |
||||
int (*uart_resume)(struct platform_device *pdev); |
||||
int (*uart_getc)(struct platform_device *pdev); |
||||
void (*uart_putc)(struct platform_device *pdev, unsigned int c); |
||||
void (*uart_flush)(struct platform_device *pdev); |
||||
void (*uart_enable)(struct platform_device *pdev); |
||||
void (*uart_disable)(struct platform_device *pdev); |
||||
|
||||
int (*uart_dev_suspend)(struct platform_device *pdev); |
||||
int (*uart_dev_resume)(struct platform_device *pdev); |
||||
|
||||
void (*fiq_enable)(struct platform_device *pdev, unsigned int fiq, |
||||
bool enable); |
||||
void (*fiq_ack)(struct platform_device *pdev, unsigned int fiq); |
||||
|
||||
void (*force_irq)(struct platform_device *pdev, unsigned int irq); |
||||
void (*force_irq_ack)(struct platform_device *pdev, unsigned int irq); |
||||
}; |
||||
|
||||
#endif |
@ -1,240 +0,0 @@ |
||||
/*
|
||||
* Copyright (C) 2014 Google, Inc. |
||||
* Author: Colin Cross <ccross@android.com> |
||||
* |
||||
* This software is licensed under the terms of the GNU General Public |
||||
* License version 2, as published by the Free Software Foundation, and |
||||
* may be copied, distributed, and modified under those terms. |
||||
* |
||||
* 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. |
||||
* |
||||
*/ |
||||
|
||||
#include <linux/ptrace.h> |
||||
#include <linux/uaccess.h> |
||||
|
||||
#include <asm/stacktrace.h> |
||||
|
||||
#include "fiq_debugger_priv.h" |
||||
|
||||
static char *mode_name(unsigned cpsr) |
||||
{ |
||||
switch (cpsr & MODE_MASK) { |
||||
case USR_MODE: return "USR"; |
||||
case FIQ_MODE: return "FIQ"; |
||||
case IRQ_MODE: return "IRQ"; |
||||
case SVC_MODE: return "SVC"; |
||||
case ABT_MODE: return "ABT"; |
||||
case UND_MODE: return "UND"; |
||||
case SYSTEM_MODE: return "SYS"; |
||||
default: return "???"; |
||||
} |
||||
} |
||||
|
||||
void fiq_debugger_dump_pc(struct fiq_debugger_output *output, |
||||
const struct pt_regs *regs) |
||||
{ |
||||
output->printf(output, " pc %08x cpsr %08x mode %s\n", |
||||
regs->ARM_pc, regs->ARM_cpsr, mode_name(regs->ARM_cpsr)); |
||||
} |
||||
|
||||
void fiq_debugger_dump_regs(struct fiq_debugger_output *output, |
||||
const struct pt_regs *regs) |
||||
{ |
||||
output->printf(output, |
||||
" r0 %08x r1 %08x r2 %08x r3 %08x\n", |
||||
regs->ARM_r0, regs->ARM_r1, regs->ARM_r2, regs->ARM_r3); |
||||
output->printf(output, |
||||
" r4 %08x r5 %08x r6 %08x r7 %08x\n", |
||||
regs->ARM_r4, regs->ARM_r5, regs->ARM_r6, regs->ARM_r7); |
||||
output->printf(output, |
||||
" r8 %08x r9 %08x r10 %08x r11 %08x mode %s\n", |
||||
regs->ARM_r8, regs->ARM_r9, regs->ARM_r10, regs->ARM_fp, |
||||
mode_name(regs->ARM_cpsr)); |
||||
output->printf(output, |
||||
" ip %08x sp %08x lr %08x pc %08x cpsr %08x\n", |
||||
regs->ARM_ip, regs->ARM_sp, regs->ARM_lr, regs->ARM_pc, |
||||
regs->ARM_cpsr); |
||||
} |
||||
|
||||
struct mode_regs { |
||||
unsigned long sp_svc; |
||||
unsigned long lr_svc; |
||||
unsigned long spsr_svc; |
||||
|
||||
unsigned long sp_abt; |
||||
unsigned long lr_abt; |
||||
unsigned long spsr_abt; |
||||
|
||||
unsigned long sp_und; |
||||
unsigned long lr_und; |
||||
unsigned long spsr_und; |
||||
|
||||
unsigned long sp_irq; |
||||
unsigned long lr_irq; |
||||
unsigned long spsr_irq; |
||||
|
||||
unsigned long r8_fiq; |
||||
unsigned long r9_fiq; |
||||
unsigned long r10_fiq; |
||||
unsigned long r11_fiq; |
||||
unsigned long r12_fiq; |
||||
unsigned long sp_fiq; |
||||
unsigned long lr_fiq; |
||||
unsigned long spsr_fiq; |
||||
}; |
||||
|
||||
static void __naked get_mode_regs(struct mode_regs *regs) |
||||
{ |
||||
asm volatile ( |
||||
"mrs r1, cpsr\n" |
||||
"msr cpsr_c, #0xd3 @(SVC_MODE | PSR_I_BIT | PSR_F_BIT)\n" |
||||
"stmia r0!, {r13 - r14}\n" |
||||
"mrs r2, spsr\n" |
||||
"msr cpsr_c, #0xd7 @(ABT_MODE | PSR_I_BIT | PSR_F_BIT)\n" |
||||
"stmia r0!, {r2, r13 - r14}\n" |
||||
"mrs r2, spsr\n" |
||||
"msr cpsr_c, #0xdb @(UND_MODE | PSR_I_BIT | PSR_F_BIT)\n" |
||||
"stmia r0!, {r2, r13 - r14}\n" |
||||
"mrs r2, spsr\n" |
||||
"msr cpsr_c, #0xd2 @(IRQ_MODE | PSR_I_BIT | PSR_F_BIT)\n" |
||||
"stmia r0!, {r2, r13 - r14}\n" |
||||
"mrs r2, spsr\n" |
||||
"msr cpsr_c, #0xd1 @(FIQ_MODE | PSR_I_BIT | PSR_F_BIT)\n" |
||||
"stmia r0!, {r2, r8 - r14}\n" |
||||
"mrs r2, spsr\n" |
||||
"stmia r0!, {r2}\n" |
||||
"msr cpsr_c, r1\n" |
||||
"bx lr\n"); |
||||
} |
||||
|
||||
|
||||
void fiq_debugger_dump_allregs(struct fiq_debugger_output *output, |
||||
const struct pt_regs *regs) |
||||
{ |
||||
struct mode_regs mode_regs; |
||||
unsigned long mode = regs->ARM_cpsr & MODE_MASK; |
||||
|
||||
fiq_debugger_dump_regs(output, regs); |
||||
get_mode_regs(&mode_regs); |
||||
|
||||
output->printf(output, |
||||
"%csvc: sp %08x lr %08x spsr %08x\n", |
||||
mode == SVC_MODE ? '*' : ' ', |
||||
mode_regs.sp_svc, mode_regs.lr_svc, mode_regs.spsr_svc); |
||||
output->printf(output, |
||||
"%cabt: sp %08x lr %08x spsr %08x\n", |
||||
mode == ABT_MODE ? '*' : ' ', |
||||
mode_regs.sp_abt, mode_regs.lr_abt, mode_regs.spsr_abt); |
||||
output->printf(output, |
||||
"%cund: sp %08x lr %08x spsr %08x\n", |
||||
mode == UND_MODE ? '*' : ' ', |
||||
mode_regs.sp_und, mode_regs.lr_und, mode_regs.spsr_und); |
||||
output->printf(output, |
||||
"%cirq: sp %08x lr %08x spsr %08x\n", |
||||
mode == IRQ_MODE ? '*' : ' ', |
||||
mode_regs.sp_irq, mode_regs.lr_irq, mode_regs.spsr_irq); |
||||
output->printf(output, |
||||
"%cfiq: r8 %08x r9 %08x r10 %08x r11 %08x r12 %08x\n", |
||||
mode == FIQ_MODE ? '*' : ' ', |
||||
mode_regs.r8_fiq, mode_regs.r9_fiq, mode_regs.r10_fiq, |
||||
mode_regs.r11_fiq, mode_regs.r12_fiq); |
||||
output->printf(output, |
||||
" fiq: sp %08x lr %08x spsr %08x\n", |
||||
mode_regs.sp_fiq, mode_regs.lr_fiq, mode_regs.spsr_fiq); |
||||
} |
||||
|
||||
struct stacktrace_state { |
||||
struct fiq_debugger_output *output; |
||||
unsigned int depth; |
||||
}; |
||||
|
||||
static int report_trace(struct stackframe *frame, void *d) |
||||
{ |
||||
struct stacktrace_state *sts = d; |
||||
|
||||
if (sts->depth) { |
||||
sts->output->printf(sts->output, |
||||
" pc: %p (%pF), lr %p (%pF), sp %p, fp %p\n", |
||||
frame->pc, frame->pc, frame->lr, frame->lr, |
||||
frame->sp, frame->fp); |
||||
sts->depth--; |
||||
return 0; |
||||
} |
||||
sts->output->printf(sts->output, " ...\n"); |
||||
|
||||
return sts->depth == 0; |
||||
} |
||||
|
||||
struct frame_tail { |
||||
struct frame_tail *fp; |
||||
unsigned long sp; |
||||
unsigned long lr; |
||||
} __attribute__((packed)); |
||||
|
||||
static struct frame_tail *user_backtrace(struct fiq_debugger_output *output, |
||||
struct frame_tail *tail) |
||||
{ |
||||
struct frame_tail buftail[2]; |
||||
|
||||
/* Also check accessibility of one struct frame_tail beyond */ |
||||
if (!access_ok(VERIFY_READ, tail, sizeof(buftail))) { |
||||
output->printf(output, " invalid frame pointer %p\n", |
||||
tail); |
||||
return NULL; |
||||
} |
||||
if (__copy_from_user_inatomic(buftail, tail, sizeof(buftail))) { |
||||
output->printf(output, |
||||
" failed to copy frame pointer %p\n", tail); |
||||
return NULL; |
||||
} |
||||
|
||||
output->printf(output, " %p\n", buftail[0].lr); |
||||
|
||||
/* frame pointers should strictly progress back up the stack
|
||||
* (towards higher addresses) */ |
||||
if (tail >= buftail[0].fp) |
||||
return NULL; |
||||
|
||||
return buftail[0].fp-1; |
||||
} |
||||
|
||||
void fiq_debugger_dump_stacktrace(struct fiq_debugger_output *output, |
||||
const struct pt_regs *regs, unsigned int depth, void *ssp) |
||||
{ |
||||
struct frame_tail *tail; |
||||
struct thread_info *real_thread_info = THREAD_INFO(ssp); |
||||
struct stacktrace_state sts; |
||||
|
||||
sts.depth = depth; |
||||
sts.output = output; |
||||
*current_thread_info() = *real_thread_info; |
||||
|
||||
if (!current) |
||||
output->printf(output, "current NULL\n"); |
||||
else |
||||
output->printf(output, "pid: %d comm: %s\n", |
||||
current->pid, current->comm); |
||||
fiq_debugger_dump_regs(output, regs); |
||||
|
||||
if (!user_mode(regs)) { |
||||
struct stackframe frame; |
||||
frame.fp = regs->ARM_fp; |
||||
frame.sp = regs->ARM_sp; |
||||
frame.lr = regs->ARM_lr; |
||||
frame.pc = regs->ARM_pc; |
||||
output->printf(output, |
||||
" pc: %p (%pF), lr %p (%pF), sp %p, fp %p\n", |
||||
regs->ARM_pc, regs->ARM_pc, regs->ARM_lr, regs->ARM_lr, |
||||
regs->ARM_sp, regs->ARM_fp); |
||||
walk_stackframe(&frame, report_trace, &sts); |
||||
return; |
||||
} |
||||
|
||||
tail = ((struct frame_tail *) regs->ARM_fp) - 1; |
||||
while (depth-- && tail && !((unsigned long) tail & 3)) |
||||
tail = user_backtrace(output, tail); |
||||
} |
@ -1,201 +0,0 @@ |
||||
/*
|
||||
* Copyright (C) 2014 Google, Inc. |
||||
* Author: Colin Cross <ccross@android.com> |
||||
* |
||||
* This software is licensed under the terms of the GNU General Public |
||||
* License version 2, as published by the Free Software Foundation, and |
||||
* may be copied, distributed, and modified under those terms. |
||||
* |
||||
* 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. |
||||
* |
||||
*/ |
||||
|
||||
#include <linux/ptrace.h> |
||||
#include <asm/stacktrace.h> |
||||
|
||||
#include "fiq_debugger_priv.h" |
||||
|
||||
static char *mode_name(const struct pt_regs *regs) |
||||
{ |
||||
if (compat_user_mode(regs)) { |
||||
return "USR"; |
||||
} else { |
||||
switch (processor_mode(regs)) { |
||||
case PSR_MODE_EL0t: return "EL0t"; |
||||
case PSR_MODE_EL1t: return "EL1t"; |
||||
case PSR_MODE_EL1h: return "EL1h"; |
||||
case PSR_MODE_EL2t: return "EL2t"; |
||||
case PSR_MODE_EL2h: return "EL2h"; |
||||
default: return "???"; |
||||
} |
||||
} |
||||
} |
||||
|
||||
void fiq_debugger_dump_pc(struct fiq_debugger_output *output, |
||||
const struct pt_regs *regs) |
||||
{ |
||||
output->printf(output, " pc %016lx cpsr %08lx mode %s\n", |
||||
regs->pc, regs->pstate, mode_name(regs)); |
||||
} |
||||
|
||||
void fiq_debugger_dump_regs_aarch32(struct fiq_debugger_output *output, |
||||
const struct pt_regs *regs) |
||||
{ |
||||
output->printf(output, " r0 %08x r1 %08x r2 %08x r3 %08x\n", |
||||
regs->compat_usr(0), regs->compat_usr(1), |
||||
regs->compat_usr(2), regs->compat_usr(3)); |
||||
output->printf(output, " r4 %08x r5 %08x r6 %08x r7 %08x\n", |
||||
regs->compat_usr(4), regs->compat_usr(5), |
||||
regs->compat_usr(6), regs->compat_usr(7)); |
||||
output->printf(output, " r8 %08x r9 %08x r10 %08x r11 %08x\n", |
||||
regs->compat_usr(8), regs->compat_usr(9), |
||||
regs->compat_usr(10), regs->compat_usr(11)); |
||||
output->printf(output, " ip %08x sp %08x lr %08x pc %08x\n", |
||||
regs->compat_usr(12), regs->compat_sp, |
||||
regs->compat_lr, regs->pc); |
||||
output->printf(output, " cpsr %08x (%s)\n", |
||||
regs->pstate, mode_name(regs)); |
||||
} |
||||
|
||||
void fiq_debugger_dump_regs_aarch64(struct fiq_debugger_output *output, |
||||
const struct pt_regs *regs) |
||||
{ |
||||
|
||||
output->printf(output, " x0 %016lx x1 %016lx\n", |
||||
regs->regs[0], regs->regs[1]); |
||||
output->printf(output, " x2 %016lx x3 %016lx\n", |
||||
regs->regs[2], regs->regs[3]); |
||||
output->printf(output, " x4 %016lx x5 %016lx\n", |
||||
regs->regs[4], regs->regs[5]); |
||||
output->printf(output, " x6 %016lx x7 %016lx\n", |
||||
regs->regs[6], regs->regs[7]); |
||||
output->printf(output, " x8 %016lx x9 %016lx\n", |
||||
regs->regs[8], regs->regs[9]); |
||||
output->printf(output, " x10 %016lx x11 %016lx\n", |
||||
regs->regs[10], regs->regs[11]); |
||||
output->printf(output, " x12 %016lx x13 %016lx\n", |
||||
regs->regs[12], regs->regs[13]); |
||||
output->printf(output, " x14 %016lx x15 %016lx\n", |
||||
regs->regs[14], regs->regs[15]); |
||||
output->printf(output, " x16 %016lx x17 %016lx\n", |
||||
regs->regs[16], regs->regs[17]); |
||||
output->printf(output, " x18 %016lx x19 %016lx\n", |
||||
regs->regs[18], regs->regs[19]); |
||||
output->printf(output, " x20 %016lx x21 %016lx\n", |
||||
regs->regs[20], regs->regs[21]); |
||||
output->printf(output, " x22 %016lx x23 %016lx\n", |
||||
regs->regs[22], regs->regs[23]); |
||||
output->printf(output, " x24 %016lx x25 %016lx\n", |
||||
regs->regs[24], regs->regs[25]); |
||||
output->printf(output, " x26 %016lx x27 %016lx\n", |
||||
regs->regs[26], regs->regs[27]); |
||||
output->printf(output, " x28 %016lx x29 %016lx\n", |
||||
regs->regs[28], regs->regs[29]); |
||||
output->printf(output, " x30 %016lx sp %016lx\n", |
||||
regs->regs[30], regs->sp); |
||||
output->printf(output, " pc %016lx cpsr %08x (%s)\n", |
||||
regs->pc, regs->pstate, mode_name(regs)); |
||||
} |
||||
|
||||
void fiq_debugger_dump_regs(struct fiq_debugger_output *output, |
||||
const struct pt_regs *regs) |
||||
{ |
||||
if (compat_user_mode(regs)) |
||||
fiq_debugger_dump_regs_aarch32(output, regs); |
||||
else |
||||
fiq_debugger_dump_regs_aarch64(output, regs); |
||||
} |
||||
|
||||
#define READ_SPECIAL_REG(x) ({ \ |
||||
u64 val; \
|
||||
asm volatile ("mrs %0, " # x : "=r"(val)); \
|
||||
val; \
|
||||
}) |
||||
|
||||
void fiq_debugger_dump_allregs(struct fiq_debugger_output *output, |
||||
const struct pt_regs *regs) |
||||
{ |
||||
u32 pstate = READ_SPECIAL_REG(CurrentEl); |
||||
bool in_el2 = (pstate & PSR_MODE_MASK) >= PSR_MODE_EL2t; |
||||
|
||||
fiq_debugger_dump_regs(output, regs); |
||||
|
||||
output->printf(output, " sp_el0 %016lx\n", |
||||
READ_SPECIAL_REG(sp_el0)); |
||||
|
||||
if (in_el2) |
||||
output->printf(output, " sp_el1 %016lx\n", |
||||
READ_SPECIAL_REG(sp_el1)); |
||||
|
||||
output->printf(output, " elr_el1 %016lx\n", |
||||
READ_SPECIAL_REG(elr_el1)); |
||||
|
||||
output->printf(output, " spsr_el1 %08lx\n", |
||||
READ_SPECIAL_REG(spsr_el1)); |
||||
|
||||
if (in_el2) { |
||||
output->printf(output, " spsr_irq %08lx\n", |
||||
READ_SPECIAL_REG(spsr_irq)); |
||||
output->printf(output, " spsr_abt %08lx\n", |
||||
READ_SPECIAL_REG(spsr_abt)); |
||||
output->printf(output, " spsr_und %08lx\n", |
||||
READ_SPECIAL_REG(spsr_und)); |
||||
output->printf(output, " spsr_fiq %08lx\n", |
||||
READ_SPECIAL_REG(spsr_fiq)); |
||||
output->printf(output, " spsr_el2 %08lx\n", |
||||
READ_SPECIAL_REG(elr_el2)); |
||||
output->printf(output, " spsr_el2 %08lx\n", |
||||
READ_SPECIAL_REG(spsr_el2)); |
||||
} |
||||
} |
||||
|
||||
struct stacktrace_state { |
||||
struct fiq_debugger_output *output; |
||||
unsigned int depth; |
||||
}; |
||||
|
||||
static int report_trace(struct stackframe *frame, void *d) |
||||
{ |
||||
struct stacktrace_state *sts = d; |
||||
|
||||
if (sts->depth) { |
||||
sts->output->printf(sts->output, "%pF:\n", frame->pc); |
||||
sts->output->printf(sts->output, |
||||
" pc %016lx fp %016lx\n", |
||||
frame->pc, frame->fp); |
||||
sts->depth--; |
||||
return 0; |
||||
} |
||||
sts->output->printf(sts->output, " ...\n"); |
||||
|
||||
return sts->depth == 0; |
||||
} |
||||
|
||||
void fiq_debugger_dump_stacktrace(struct fiq_debugger_output *output, |
||||
const struct pt_regs *regs, unsigned int depth, void *ssp) |
||||
{ |
||||
struct thread_info *real_thread_info = THREAD_INFO(ssp); |
||||
struct stacktrace_state sts; |
||||
|
||||
sts.depth = depth; |
||||
sts.output = output; |
||||
*current_thread_info() = *real_thread_info; |
||||
|
||||
if (!current) |
||||
output->printf(output, "current NULL\n"); |
||||
else |
||||
output->printf(output, "pid: %d comm: %s\n", |
||||
current->pid, current->comm); |
||||
fiq_debugger_dump_regs(output, regs); |
||||
|
||||
if (!user_mode(regs)) { |
||||
struct stackframe frame; |
||||
frame.fp = regs->regs[29]; |
||||
frame.pc = regs->pc; |
||||
output->printf(output, "\n"); |
||||
walk_stackframe(current, &frame, report_trace, &sts); |
||||
} |
||||
} |
@ -1,37 +0,0 @@ |
||||
/*
|
||||
* Copyright (C) 2014 Google, Inc. |
||||
* Author: Colin Cross <ccross@android.com> |
||||
* |
||||
* This software is licensed under the terms of the GNU General Public |
||||
* License version 2, as published by the Free Software Foundation, and |
||||
* may be copied, distributed, and modified under those terms. |
||||
* |
||||
* 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. |
||||
* |
||||
*/ |
||||
|
||||
#ifndef _FIQ_DEBUGGER_PRIV_H_ |
||||
#define _FIQ_DEBUGGER_PRIV_H_ |
||||
|
||||
#define THREAD_INFO(sp) ((struct thread_info *) \ |
||||
((unsigned long)(sp) & ~(THREAD_SIZE - 1))) |
||||
|
||||
struct fiq_debugger_output { |
||||
void (*printf)(struct fiq_debugger_output *output, const char *fmt, ...); |
||||
}; |
||||
|
||||
struct pt_regs; |
||||
|
||||
void fiq_debugger_dump_pc(struct fiq_debugger_output *output, |
||||
const struct pt_regs *regs); |
||||
void fiq_debugger_dump_regs(struct fiq_debugger_output *output, |
||||
const struct pt_regs *regs); |
||||
void fiq_debugger_dump_allregs(struct fiq_debugger_output *output, |
||||
const struct pt_regs *regs); |
||||
void fiq_debugger_dump_stacktrace(struct fiq_debugger_output *output, |
||||
const struct pt_regs *regs, unsigned int depth, void *ssp); |
||||
|
||||
#endif |
@ -1,94 +0,0 @@ |
||||
/*
|
||||
* drivers/staging/android/fiq_debugger/fiq_debugger_ringbuf.h |
||||
* |
||||
* simple lockless ringbuffer |
||||
* |
||||
* Copyright (C) 2010 Google, Inc. |
||||
* |
||||
* This software is licensed under the terms of the GNU General Public |
||||
* License version 2, as published by the Free Software Foundation, and |
||||
* may be copied, distributed, and modified under those terms. |
||||
* |
||||
* 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. |
||||
*/ |
||||
|
||||
#include <linux/kernel.h> |
||||
#include <linux/slab.h> |
||||
|
||||
struct fiq_debugger_ringbuf { |
||||
int len; |
||||
int head; |
||||
int tail; |
||||
u8 buf[]; |
||||
}; |
||||
|
||||
|
||||
static inline struct fiq_debugger_ringbuf *fiq_debugger_ringbuf_alloc(int len) |
||||
{ |
||||
struct fiq_debugger_ringbuf *rbuf; |
||||
|
||||
rbuf = kzalloc(sizeof(*rbuf) + len, GFP_KERNEL); |
||||
if (rbuf == NULL) |
||||
return NULL; |
||||
|
||||
rbuf->len = len; |
||||
rbuf->head = 0; |
||||
rbuf->tail = 0; |
||||
smp_mb(); |
||||
|
||||
return rbuf; |
||||
} |
||||
|
||||
static inline void fiq_debugger_ringbuf_free(struct fiq_debugger_ringbuf *rbuf) |
||||
{ |
||||
kfree(rbuf); |
||||
} |
||||
|
||||
static inline int fiq_debugger_ringbuf_level(struct fiq_debugger_ringbuf *rbuf) |
||||
{ |
||||
int level = rbuf->head - rbuf->tail; |
||||
|
||||
if (level < 0) |
||||
level = rbuf->len + level; |
||||
|
||||
return level; |
||||
} |
||||
|
||||
static inline int fiq_debugger_ringbuf_room(struct fiq_debugger_ringbuf *rbuf) |
||||
{ |
||||
return rbuf->len - fiq_debugger_ringbuf_level(rbuf) - 1; |
||||
} |
||||
|
||||
static inline u8 |
||||
fiq_debugger_ringbuf_peek(struct fiq_debugger_ringbuf *rbuf, int i) |
||||
{ |
||||
return rbuf->buf[(rbuf->tail + i) % rbuf->len]; |
||||
} |
||||
|
||||
static inline int |
||||
fiq_debugger_ringbuf_consume(struct fiq_debugger_ringbuf *rbuf, int count) |
||||
{ |
||||
count = min(count, fiq_debugger_ringbuf_level(rbuf)); |
||||
|
||||
rbuf->tail = (rbuf->tail + count) % rbuf->len; |
||||
smp_mb(); |
||||
|
||||
return count; |
||||
} |
||||
|
||||
static inline int |
||||
fiq_debugger_ringbuf_push(struct fiq_debugger_ringbuf *rbuf, u8 datum) |
||||
{ |
||||
if (fiq_debugger_ringbuf_room(rbuf) == 0) |
||||
return 0; |
||||
|
||||
rbuf->buf[rbuf->head] = datum; |
||||
smp_mb(); |
||||
rbuf->head = (rbuf->head + 1) % rbuf->len; |
||||
smp_mb(); |
||||
|
||||
return 1; |
||||
} |
@ -1,56 +0,0 @@ |
||||
/*
|
||||
* Copyright (C) 2014 Google, Inc. |
||||
* |
||||
* This software is licensed under the terms of the GNU General Public |
||||
* License version 2, as published by the Free Software Foundation, and |
||||
* may be copied, distributed, and modified under those terms. |
||||
* |
||||
* 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. |
||||
* |
||||
*/ |
||||
|
||||
#include <linux/kernel.h> |
||||
#include <linux/spinlock.h> |
||||
#include <linux/pstore_ram.h> |
||||
|
||||
#include "fiq_watchdog.h" |
||||
#include "fiq_debugger_priv.h" |
||||
|
||||
static DEFINE_RAW_SPINLOCK(fiq_watchdog_lock); |
||||
|
||||
static void fiq_watchdog_printf(struct fiq_debugger_output *output, |
||||
const char *fmt, ...) |
||||
{ |
||||
char buf[256]; |
||||
va_list ap; |
||||
int len; |
||||
|
||||
va_start(ap, fmt); |
||||
len = vscnprintf(buf, sizeof(buf), fmt, ap); |
||||
va_end(ap); |
||||
|
||||
ramoops_console_write_buf(buf, len); |
||||
} |
||||
|
||||
struct fiq_debugger_output fiq_watchdog_output = { |
||||
.printf = fiq_watchdog_printf, |
||||
}; |
||||
|
||||
void fiq_watchdog_triggered(const struct pt_regs *regs, void *svc_sp) |
||||
{ |
||||
char msg[24]; |
||||
int len; |
||||
|
||||
raw_spin_lock(&fiq_watchdog_lock); |
||||
|
||||
len = scnprintf(msg, sizeof(msg), "watchdog fiq cpu %d\n", |
||||
THREAD_INFO(svc_sp)->cpu); |
||||
ramoops_console_write_buf(msg, len); |
||||
|
||||
fiq_debugger_dump_stacktrace(&fiq_watchdog_output, regs, 100, svc_sp); |
||||
|
||||
raw_spin_unlock(&fiq_watchdog_lock); |
||||
} |
@ -1,20 +0,0 @@ |
||||
/*
|
||||
* Copyright (C) 2014 Google, Inc. |
||||
* |
||||
* This software is licensed under the terms of the GNU General Public |
||||
* License version 2, as published by the Free Software Foundation, and |
||||
* may be copied, distributed, and modified under those terms. |
||||
* |
||||
* 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. |
||||
* |
||||
*/ |
||||
|
||||
#ifndef _FIQ_WATCHDOG_H_ |
||||
#define _FIQ_WATCHDOG_H_ |
||||
|
||||
void fiq_watchdog_triggered(const struct pt_regs *regs, void *svc_sp); |
||||
|
||||
#endif |
Loading…
Reference in new issue