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/

The reverts specific to android-4.14 are as follows:

Revert "ANDROID: fiq_debugger: Remove wakelock.h dependencies"
This reverts commit f9cbd12ed7.

Revert "ANDROID: fiq_debugger: Add fiq_debugger.disable option"
This reverts commit 76d292f95a.

Revert "ANDROID: fiq_debugger: Add option to apply uart overlay by
        FIQ_DEBUGGER_UART_OVERLAY"
This reverts commit 0ff9e291c1.

Revert "ANDROID: fiq_debugger: Add fiq_watchdog_triggered api"
This reverts commit 9c027e6c23.

Revert "ANDROID: fiq_debugger: Call fiq_debugger_printf through a
        function pointer from cpu specific code"
This reverts commit 9200a45dc9.

Revert "ANDROID: fiq_debugger: add ARM64 support"
This reverts commit c9d6bc7ab0.

Revert "ANDROID: fiq_debugger: split arm support into fiq_debugger_arm.c"
This reverts commit efffceb1e9.

Revert "ANDROID: fiq_debugger: use pt_regs for registers"
This reverts commit bf32f8accc.

Revert "ANDROID: fiq_debugger: allow compiling without CONFIG_FIQ_GLUE"
This reverts commit 16c3248941.

Revert "ANDROID: fiq_debugger: rename debug->fiq_debugger"
This reverts commit d241f1dfc9.

Revert "ANDROID: fiq_debugger: move into
        drivers/staging/android/fiq_debugger/"
This reverts commit 0dc1cccb4f.

Revert "ANDROID: ARM: fiq_debugger: Update tty code for 3.9"
This reverts commit 4b55137d5e.

Revert "ANDROID: ARM: fiq_debugger: lock between tty and console writes"
This reverts commit a8be462329.

Revert "ANDROID: ARM: fiq_debugger: add process context reboot command"
This reverts commit cb5774b503.

Revert "ANDROID: ARM: fiq_debugger: fix multiple consoles and make it
        a preferred console"
This reverts commit aecfa53f35.

Revert "ANDROID: ARM: fiq_debugger: add support for kgdb"
This reverts commit 992dbb2a9a.

Revert "ANDROID: ARM: fiq_debugger: add debug_putc"
This reverts commit 5d12c56f2a.

Revert "ANDROID: ARM: fiq_debugger: add support for reboot commands"
This reverts commit 14dbf8675b.

Revert "ANDROID: ARM: fiq_debugger: Add generic fiq serial debugger"
This reverts commit 05e1c7f617.

Revert "ANDROID: ARM: fiq_glue: Add custom fiq return handler api."
This reverts commit e329aaf322.

Revert "ANDROID: ARM: fiq_glue: Add fiq_glue"
This reverts commit 47fe2f8d76.

Signed-off-by: Mark Salyzyn <salyzyn@google.com>
Bug: 32402555
Bug: 36101220
Change-Id: I3f74b1ff5e4971d619bcb37a911fed68fbb538d5
tirimbino
Mark Salyzyn 6 years ago
parent 54236917c6
commit a9d0871a56
  1. 4
      arch/arm/common/Kconfig
  2. 1
      arch/arm/common/Makefile
  3. 118
      arch/arm/common/fiq_glue.S
  4. 147
      arch/arm/common/fiq_glue_setup.c
  5. 33
      arch/arm/include/asm/fiq_glue.h
  6. 2
      drivers/staging/android/Kconfig
  7. 1
      drivers/staging/android/Makefile
  8. 58
      drivers/staging/android/fiq_debugger/Kconfig
  9. 4
      drivers/staging/android/fiq_debugger/Makefile
  10. 1246
      drivers/staging/android/fiq_debugger/fiq_debugger.c
  11. 64
      drivers/staging/android/fiq_debugger/fiq_debugger.h
  12. 240
      drivers/staging/android/fiq_debugger/fiq_debugger_arm.c
  13. 201
      drivers/staging/android/fiq_debugger/fiq_debugger_arm64.c
  14. 37
      drivers/staging/android/fiq_debugger/fiq_debugger_priv.h
  15. 94
      drivers/staging/android/fiq_debugger/fiq_debugger_ringbuf.h
  16. 56
      drivers/staging/android/fiq_debugger/fiq_watchdog.c
  17. 20
      drivers/staging/android/fiq_debugger/fiq_watchdog.h

@ -15,7 +15,3 @@ config SHARP_PARAM
config SHARP_SCOOP
bool
config FIQ_GLUE
bool
select FIQ

@ -5,7 +5,6 @@
obj-y += firmware.o
obj-$(CONFIG_FIQ_GLUE) += fiq_glue.o fiq_glue_setup.o
obj-$(CONFIG_SA1111) += sa1111.o
obj-$(CONFIG_DMABOUNCE) += dmabounce.o
obj-$(CONFIG_SHARP_LOCOMO) += locomo.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);
}

@ -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

@ -25,8 +25,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_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…
Cancel
Save