ANDROID: fiq_debugger: remove
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/ Signed-off-by: Mark Salyzyn <salyzyn@google.com> Bug: 32402555 Bug: 36101220 Change-Id: I3f74b1ff5e4971d619bcb37a911fed68fbb538d5
This commit is contained in:
parent
4bfd158200
commit
1850744793
16 changed files with 0 additions and 2296 deletions
|
@ -17,7 +17,3 @@ config SHARP_PARAM
|
|||
|
||||
config SHARP_SCOOP
|
||||
bool
|
||||
|
||||
config FIQ_GLUE
|
||||
bool
|
||||
select FIQ
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
|
||||
obj-y += firmware.o
|
||||
|
||||
obj-$(CONFIG_FIQ_GLUE) += fiq_glue.o fiq_glue_setup.o
|
||||
obj-$(CONFIG_ICST) += icst.o
|
||||
obj-$(CONFIG_SA1111) += sa1111.o
|
||||
obj-$(CONFIG_DMABOUNCE) += dmabounce.o
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -86,8 +86,6 @@ config ANDROID_VSOC
|
|||
|
||||
source "drivers/staging/android/ion/Kconfig"
|
||||
|
||||
source "drivers/staging/android/fiq_debugger/Kconfig"
|
||||
|
||||
endif # if ANDROID
|
||||
|
||||
endmenu
|
||||
|
|
|
@ -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_TIMED_OUTPUT) += timed_output.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,202 +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 sp %016lx fp %016lx\n",
|
||||
frame->pc, frame->sp, 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.sp = regs->sp;
|
||||
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…
Add table
Reference in a new issue