debug: improve ftrace_ramoops for io trace [2/2]

PD#SWPL-6028

Problem:
improve ftrace_ramoops to debug bus hang

Solution:
1. in uboot
setenv initargs $initargs ramoops_io_en=1 loglevel=3;save;reset
2. in linux command line:
cat /sys/module/kernel/parameters/ramoops_io_en
to check if success.
3. after watchdog reboot, get trace data with:
cat /sys/fs/pstore/ftrace-ramoops-0

Verify:
TL1 x301

Change-Id: If1a2582b40a3ded31eedef5355eb0b8a5bf495c3
Signed-off-by: Jianxin Pan <jianxin.pan@amlogic.com>
This commit is contained in:
Jianxin Pan
2019-04-03 19:16:50 +08:00
committed by Luke Go
parent a749b4dfa5
commit a9cd2cd9f1
21 changed files with 445 additions and 28 deletions

View File

@@ -14530,6 +14530,7 @@ AMLOGIC DEBUG
M: Jianxin Pan <jianxin.pan@amlogic.com>
M: Tao Guo <tao.guo@amlogic.com>
F: drivers/amlogic/debug/*
F: include/linux/amlogic/debug*.h
AMLOGIC G12A spdif channel status
M: xing wang<xing.wang@amlogic.com>

View File

@@ -31,6 +31,9 @@
#include <asm-generic/pci_iomap.h>
#include <xen/xen.h>
#ifdef CONFIG_AMLOGIC_MODIFY
#include <linux/amlogic/debug_ftrace_ramoops.h>
#endif
/*
* ISA I/O bus memory addresses are 1:1 with the physical address.
*/
@@ -73,17 +76,29 @@ void __raw_readsl(const volatile void __iomem *addr, void *data, int longlen);
#define __raw_writew __raw_writew
static inline void __raw_writew(u16 val, volatile void __iomem *addr)
{
#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE
pstore_ftrace_io_wr((unsigned long)addr, (unsigned long)val);
#endif
asm volatile("strh %1, %0"
: : "Q" (*(volatile u16 __force *)addr), "r" (val));
#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE
pstore_ftrace_io_wr_end((unsigned long)addr, (unsigned long)val);
#endif
}
#define __raw_readw __raw_readw
static inline u16 __raw_readw(const volatile void __iomem *addr)
{
u16 val;
#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE
pstore_ftrace_io_rd((unsigned long)addr);
#endif
asm volatile("ldrh %0, %1"
: "=r" (val)
: "Q" (*(volatile u16 __force *)addr));
#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE
pstore_ftrace_io_rd_end((unsigned long)addr);
#endif
return val;
}
#endif
@@ -91,24 +106,42 @@ static inline u16 __raw_readw(const volatile void __iomem *addr)
#define __raw_writeb __raw_writeb
static inline void __raw_writeb(u8 val, volatile void __iomem *addr)
{
#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE
pstore_ftrace_io_wr((unsigned long)addr, (unsigned long)val);
#endif
asm volatile("strb %1, %0"
: : "Qo" (*(volatile u8 __force *)addr), "r" (val));
#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE
pstore_ftrace_io_wr_end((unsigned long)addr, (unsigned long)val);
#endif
}
#define __raw_writel __raw_writel
static inline void __raw_writel(u32 val, volatile void __iomem *addr)
{
#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE
pstore_ftrace_io_wr((unsigned long)addr, (unsigned long)val);
#endif
asm volatile("str %1, %0"
: : "Qo" (*(volatile u32 __force *)addr), "r" (val));
#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE
pstore_ftrace_io_wr_end((unsigned long)addr, (unsigned long)val);
#endif
}
#define __raw_readb __raw_readb
static inline u8 __raw_readb(const volatile void __iomem *addr)
{
u8 val;
#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE
pstore_ftrace_io_rd((unsigned long)addr);
#endif
asm volatile("ldrb %0, %1"
: "=r" (val)
: "Qo" (*(volatile u8 __force *)addr));
#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE
pstore_ftrace_io_rd_end((unsigned long)addr);
#endif
return val;
}
@@ -116,9 +149,15 @@ static inline u8 __raw_readb(const volatile void __iomem *addr)
static inline u32 __raw_readl(const volatile void __iomem *addr)
{
u32 val;
#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE
pstore_ftrace_io_rd((unsigned long)addr);
#endif
asm volatile("ldr %0, %1"
: "=r" (val)
: "Qo" (*(volatile u32 __force *)addr));
#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE
pstore_ftrace_io_rd_end((unsigned long)addr);
#endif
return val;
}
@@ -317,7 +356,13 @@ static inline void memset_io(volatile void __iomem *dst, unsigned c,
size_t count)
{
extern void mmioset(void *, unsigned int, size_t);
#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE
pstore_ftrace_io_wr((unsigned long)dst, (unsigned long)count);
#endif
mmioset((void __force *)dst, c, count);
#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE
pstore_ftrace_io_wr_end((unsigned long)dst, (unsigned long)count);
#endif
}
#define memset_io(dst,c,count) memset_io(dst,c,count)
@@ -325,7 +370,13 @@ static inline void memcpy_fromio(void *to, const volatile void __iomem *from,
size_t count)
{
extern void mmiocpy(void *, const void *, size_t);
#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE
pstore_ftrace_io_wr((unsigned long)to, (unsigned long)count);
#endif
mmiocpy(to, (const void __force *)from, count);
#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE
pstore_ftrace_io_wr_end((unsigned long)to, (unsigned long)count);
#endif
}
#define memcpy_fromio(to,from,count) memcpy_fromio(to,from,count)
@@ -333,7 +384,13 @@ static inline void memcpy_toio(volatile void __iomem *to, const void *from,
size_t count)
{
extern void mmiocpy(void *, const void *, size_t);
#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE
pstore_ftrace_io_wr((unsigned long)to, (unsigned long)count);
#endif
mmiocpy((void __force *)to, from, count);
#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE
pstore_ftrace_io_wr_end((unsigned long)to, (unsigned long)count);
#endif
}
#define memcpy_toio(to,from,count) memcpy_toio(to,from,count)

View File

@@ -33,42 +33,74 @@
#include <asm/cpufeature.h>
#include <xen/xen.h>
#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE
#include <linux/amlogic/debug_ftrace_ramoops.h>
#endif
/*
* Generic IO read/write. These perform native-endian accesses.
*/
#define __raw_writeb __raw_writeb
static inline void __raw_writeb(u8 val, volatile void __iomem *addr)
{
#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE
pstore_ftrace_io_wr((unsigned long)addr, (unsigned long)val);
#endif
asm volatile("strb %w0, [%1]" : : "rZ" (val), "r" (addr));
#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE
pstore_ftrace_io_wr_end((unsigned long)addr, (unsigned long)val);
#endif
}
#define __raw_writew __raw_writew
static inline void __raw_writew(u16 val, volatile void __iomem *addr)
{
#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE
pstore_ftrace_io_wr((unsigned long)addr, (unsigned long)val);
#endif
asm volatile("strh %w0, [%1]" : : "rZ" (val), "r" (addr));
#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE
pstore_ftrace_io_wr_end((unsigned long)addr, (unsigned long)val);
#endif
}
#define __raw_writel __raw_writel
static inline void __raw_writel(u32 val, volatile void __iomem *addr)
{
#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE
pstore_ftrace_io_wr((unsigned long)addr, (unsigned long)val);
#endif
asm volatile("str %w0, [%1]" : : "rZ" (val), "r" (addr));
#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE
pstore_ftrace_io_wr_end((unsigned long)addr, (unsigned long)val);
#endif
}
#define __raw_writeq __raw_writeq
static inline void __raw_writeq(u64 val, volatile void __iomem *addr)
{
#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE
pstore_ftrace_io_wr((unsigned long)addr, (unsigned long)val);
#endif
asm volatile("str %x0, [%1]" : : "rZ" (val), "r" (addr));
#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE
pstore_ftrace_io_wr_end((unsigned long)addr, (unsigned long)val);
#endif
}
#define __raw_readb __raw_readb
static inline u8 __raw_readb(const volatile void __iomem *addr)
{
u8 val;
#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE
pstore_ftrace_io_rd((unsigned long)addr);
#endif
asm volatile(ALTERNATIVE("ldrb %w0, [%1]",
"ldarb %w0, [%1]",
ARM64_WORKAROUND_DEVICE_LOAD_ACQUIRE)
: "=r" (val) : "r" (addr));
#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE
pstore_ftrace_io_rd_end((unsigned long)addr);
#endif
return val;
}
@@ -77,10 +109,16 @@ static inline u16 __raw_readw(const volatile void __iomem *addr)
{
u16 val;
#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE
pstore_ftrace_io_rd((unsigned long)addr);
#endif
asm volatile(ALTERNATIVE("ldrh %w0, [%1]",
"ldarh %w0, [%1]",
ARM64_WORKAROUND_DEVICE_LOAD_ACQUIRE)
: "=r" (val) : "r" (addr));
#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE
pstore_ftrace_io_rd_end((unsigned long)addr);
#endif
return val;
}
@@ -88,10 +126,16 @@ static inline u16 __raw_readw(const volatile void __iomem *addr)
static inline u32 __raw_readl(const volatile void __iomem *addr)
{
u32 val;
#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE
pstore_ftrace_io_rd((unsigned long)addr);
#endif
asm volatile(ALTERNATIVE("ldr %w0, [%1]",
"ldar %w0, [%1]",
ARM64_WORKAROUND_DEVICE_LOAD_ACQUIRE)
: "=r" (val) : "r" (addr));
#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE
pstore_ftrace_io_rd_end((unsigned long)addr);
#endif
return val;
}
@@ -99,10 +143,16 @@ static inline u32 __raw_readl(const volatile void __iomem *addr)
static inline u64 __raw_readq(const volatile void __iomem *addr)
{
u64 val;
#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE
pstore_ftrace_io_rd((unsigned long)addr);
#endif
asm volatile(ALTERNATIVE("ldr %0, [%1]",
"ldar %0, [%1]",
ARM64_WORKAROUND_DEVICE_LOAD_ACQUIRE)
: "=r" (val) : "r" (addr));
#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE
pstore_ftrace_io_rd_end((unsigned long)addr);
#endif
return val;
}

View File

@@ -18,13 +18,21 @@
#include <linux/export.h>
#include <linux/types.h>
#define SKIP_IO_TRACE
#include <linux/io.h>
#undef SKIP_IO_TRACE
#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE
#include <linux/amlogic/debug_ftrace_ramoops.h>
#endif
/*
* Copy data from IO memory space to "real" memory space.
*/
void __memcpy_fromio(void *to, const volatile void __iomem *from, size_t count)
{
#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE
pstore_ftrace_io_rd((unsigned long)addr);
#endif
while (count && !IS_ALIGNED((unsigned long)from, 8)) {
*(u8 *)to = __raw_readb(from);
from++;
@@ -45,6 +53,9 @@ void __memcpy_fromio(void *to, const volatile void __iomem *from, size_t count)
to++;
count--;
}
#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE
pstore_ftrace_io_rd_end((unsigned long)addr);
#endif
}
EXPORT_SYMBOL(__memcpy_fromio);
@@ -53,6 +64,9 @@ EXPORT_SYMBOL(__memcpy_fromio);
*/
void __memcpy_toio(volatile void __iomem *to, const void *from, size_t count)
{
#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE
pstore_ftrace_io_wr((unsigned long)addr, 0x1234);
#endif
while (count && !IS_ALIGNED((unsigned long)to, 8)) {
__raw_writeb(*(u8 *)from, to);
from++;
@@ -73,6 +87,9 @@ void __memcpy_toio(volatile void __iomem *to, const void *from, size_t count)
to++;
count--;
}
#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE
pstore_ftrace_io_wr_end((unsigned long)addr, 0x1234);
#endif
}
EXPORT_SYMBOL(__memcpy_toio);
@@ -83,6 +100,9 @@ void __memset_io(volatile void __iomem *dst, int c, size_t count)
{
u64 qc = (u8)c;
#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE
pstore_ftrace_io_wr((unsigned long)addr, 0xabcd);
#endif
qc |= qc << 8;
qc |= qc << 16;
qc |= qc << 32;
@@ -104,5 +124,8 @@ void __memset_io(volatile void __iomem *dst, int c, size_t count)
dst++;
count--;
}
#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE
pstore_ftrace_io_wr_end((unsigned long)addr, 0xabcd);
#endif
}
EXPORT_SYMBOL(__memset_io);

View File

@@ -19,3 +19,15 @@ config AMLOGIC_DEBUG_ATRACE
default y
help
Add android atrace compatible function
config AMLOGIC_DEBUG_FTRACE_PSTORE
bool "Amlogic ftrace pstore debug"
depends on AMLOGIC_DEBUG
depends on PSTORE_FTRACE
default y
help
Dump function call and register access to ramoops after watchdog
reboot.
Enable if doubt.

View File

@@ -1,2 +1,3 @@
obj-$(CONFIG_AMLOGIC_DEBUG_LOCKUP) += debug_lockup.o
obj-$(CONFIG_AMLOGIC_DEBUG_ATRACE) += meson_atrace.o
obj-$(CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE)+= debug_ftrace_ramoops.o

View File

@@ -0,0 +1,149 @@
/*
* drivers/amlogic/debug/debug_ftrace_ramoops.c
*
* Copyright (C) 2017 Amlogic, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* 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/compiler.h>
#include <linux/irqflags.h>
#include <linux/percpu.h>
#include <linux/smp.h>
#include <linux/atomic.h>
#include <linux/types.h>
#include <linux/ftrace.h>
#include <linux/fs.h>
#include <linux/debugfs.h>
#include <linux/err.h>
#include <linux/amlogic/debug_ftrace_ramoops.h>
#include <../../../fs/pstore/internal.h>
#include <linux/trace_clock.h>
#include <linux/percpu.h>
#include <linux/moduleparam.h>
static DEFINE_PER_CPU(int, en);
static DEFINE_PER_CPU(unsigned long, irq_flag);
#define IRQ_D 1
unsigned int dump_iomap;
core_param(dump_iomap, dump_iomap, uint, 0664);
unsigned int ramoops_ftrace_en;
EXPORT_SYMBOL(ramoops_ftrace_en);
int ramoops_io_en;
EXPORT_SYMBOL(ramoops_io_en);
core_param(ramoops_io_en, ramoops_io_en, int, 0664);
const char *record_name[PSTORE_FLAG_IO_MAX] = {
"NULL",
"FUNC",
"IO-R",
"IO-W",
"IO-R-E",
"IO-W-E",
};
void notrace pstore_ftrace_save(struct pstore_ftrace_record *rec)
{
int cpu = raw_smp_processor_id();
if (unlikely(oops_in_progress) || unlikely(per_cpu(en, cpu)))
return;
per_cpu(en, cpu) = 1;
pstore_ftrace_encode_cpu(rec, cpu);
strlcpy(rec->comm, current->comm, sizeof(rec->comm) - 1);
rec->pid = current->pid;
rec->time = trace_clock_local();
psinfo->write_buf(PSTORE_TYPE_FTRACE, 0, NULL, 0, (void *)rec,
0, sizeof(*rec), psinfo);
per_cpu(en, cpu) = 0;
}
EXPORT_SYMBOL(pstore_ftrace_save);
static void notrace pstore_function_dump(struct pstore_ftrace_record *rec,
struct seq_file *s)
{
unsigned long sec = 0, ms = 0;
unsigned long long time = rec->time;
do_div(time, 1000000);
sec = (unsigned long)time / 1000;
ms = (unsigned long)time % 1000;
seq_printf(s, "[%04ld.%03ld@%d] <%5d-%s> <%pf <- %pF>\n",
sec, ms, pstore_ftrace_decode_cpu(rec), rec->pid, rec->comm,
(void *)rec->ip, (void *)rec->parent_ip);
}
void notrace pstore_io_rw_dump(struct pstore_ftrace_record *rec,
struct seq_file *s)
{
unsigned long sec = 0, ms = 0;
unsigned long long time = rec->time;
unsigned int cpu = pstore_ftrace_decode_cpu(rec);
do_div(time, 1000000);
sec = (unsigned long)time / 1000;
ms = (unsigned long)time % 1000;
seq_printf(s, "[%04ld.%03ld@%d] <%5d-%6s> <%6s %08lx-%8lx> <%pf <- %pF>\n",
sec, ms, cpu, rec->pid, rec->comm, record_name[rec->flag],
rec->val1, (rec->flag == PSTORE_FLAG_IO_W) ? rec->val2 : 0,
(void *)rec->ip, (void *)rec->parent_ip);
}
void notrace pstore_ftrace_dump(struct pstore_ftrace_record *rec,
struct seq_file *s)
{
switch (rec->flag & PSTORE_FLAG_MASK) {
case PSTORE_FLAG_FUNC:
pstore_function_dump(rec, s);
break;
case PSTORE_FLAG_IO_R:
case PSTORE_FLAG_IO_W:
case PSTORE_FLAG_IO_W_END:
case PSTORE_FLAG_IO_R_END:
pstore_io_rw_dump(rec, s);
break;
default:
seq_printf(s, "Unknown Msg:%x\n", rec->flag);
}
}
void notrace pstore_io_save(unsigned long reg, unsigned long val,
unsigned long parant, unsigned int flag)
{
struct pstore_ftrace_record rec;
int cpu = get_cpu();
put_cpu();
if (!ramoops_ftrace_en || !ramoops_io_en)
return;
if ((flag == PSTORE_FLAG_IO_R || flag == PSTORE_FLAG_IO_W) && IRQ_D)
local_irq_save(per_cpu(irq_flag, cpu));
rec.ip = CALLER_ADDR0;
rec.parent_ip = parant;
rec.flag = flag;
rec.val1 = reg;
rec.val2 = val;
pstore_ftrace_save(&rec);
if ((flag == PSTORE_FLAG_IO_R_END || flag == PSTORE_FLAG_IO_W_END)
&& IRQ_D)
local_irq_restore(per_cpu(irq_flag, cpu));
}
EXPORT_SYMBOL(pstore_io_save);

View File

@@ -40,7 +40,7 @@ static const struct of_device_id iomap_dt_match[] = {
static void __iomem *meson_reg_map[IO_BUS_MAX] = { NULL };
static uint meson_reg_max[IO_BUS_MAX] = { 0 };
int aml_reg_read(u32 bus_type, unsigned int reg, unsigned int *val)
inline int aml_reg_read(u32 bus_type, unsigned int reg, unsigned int *val)
{
if (
bus_type < IO_BUS_MAX &&
@@ -53,7 +53,7 @@ int aml_reg_read(u32 bus_type, unsigned int reg, unsigned int *val)
}
EXPORT_SYMBOL(aml_reg_read);
int aml_reg_write(u32 bus_type, unsigned int reg, unsigned int val)
inline int aml_reg_write(u32 bus_type, unsigned int reg, unsigned int val)
{
if (
bus_type < IO_BUS_MAX &&

View File

@@ -52,7 +52,7 @@ enum {
static void __iomem *codecio_reg_map[CODECIO_BUS_MAX];
static u32 codecio_reg_max[CODECIO_BUS_MAX];
static int codecio_reg_read(u32 bus_type, unsigned int reg, unsigned int *val)
static inline int codecio_reg_read(u32 bus_type, u32 reg, u32 *val)
{
if (bus_type < CODECIO_BUS_MAX) {
if (
@@ -71,7 +71,7 @@ static int codecio_reg_read(u32 bus_type, unsigned int reg, unsigned int *val)
return -1;
}
static int codecio_reg_write(u32 bus_type, unsigned int reg, unsigned int val)
static inline int codecio_reg_write(u32 bus_type, u32 reg, u32 val)
{
if (bus_type < CODECIO_BUS_MAX) {
if (

View File

@@ -49,20 +49,6 @@
MESON_CPU_MAJOR_ID_SM1, \
MESON_CPU_MAJOR_ID_TM2, \
0}
int codec_apb_read(unsigned int reg)
{
unsigned int val = 0;
aml_reg_read(IO_APB_BUS_BASE, reg << 2, &val);
return val;
}
EXPORT_SYMBOL(codec_apb_read);
void codec_apb_write(unsigned int reg, unsigned int val)
{
aml_reg_write(IO_APB_BUS_BASE, reg << 2, val);
}
EXPORT_SYMBOL(codec_apb_write);
static struct chip_register_ops m8_ops[] __initdata = {
{IO_DOS_BUS, 0, codecio_read_dosbus, codecio_write_dosbus},

View File

@@ -15,6 +15,7 @@
*
*/
#define SKIP_IO_TRACE
#include <linux/clk.h>
#include <linux/console.h>
#include <linux/delay.h>

View File

@@ -20,6 +20,7 @@
* As such, the enable set/clear, pending set/clear and active bit
* registers are banked per-cpu for these sources.
*/
#define SKIP_IO_TRACE
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/err.h>

View File

@@ -27,6 +27,10 @@
#include <asm/barrier.h>
#include "internal.h"
#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE
#include <linux/amlogic/debug_ftrace_ramoops.h>
#endif
static void notrace pstore_ftrace_call(unsigned long ip,
unsigned long parent_ip,
struct ftrace_ops *op,
@@ -39,13 +43,16 @@ static void notrace pstore_ftrace_call(unsigned long ip,
return;
local_irq_save(flags);
rec.ip = ip;
rec.parent_ip = parent_ip;
#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE
rec.flag = PSTORE_FLAG_FUNC;
pstore_ftrace_save(&rec);
#else
pstore_ftrace_encode_cpu(&rec, raw_smp_processor_id());
psinfo->write_buf(PSTORE_TYPE_FTRACE, 0, NULL, 0, (void *)&rec,
0, sizeof(rec), psinfo);
#endif
local_irq_restore(flags);
}

View File

@@ -37,6 +37,7 @@
#include <linux/spinlock.h>
#include <linux/uaccess.h>
#include <linux/syslog.h>
#include <linux/amlogic/debug_ftrace_ramoops.h>
#include "internal.h"
@@ -107,10 +108,13 @@ static int pstore_ftrace_seq_show(struct seq_file *s, void *v)
struct pstore_ftrace_seq_data *data = v;
struct pstore_ftrace_record *rec = (void *)(ps->data + data->off);
#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE
pstore_ftrace_dump(rec, s);
#else
seq_printf(s, "%d %08lx %08lx %pf <- %pF\n",
pstore_ftrace_decode_cpu(rec), rec->ip, rec->parent_ip,
(void *)rec->ip, (void *)rec->parent_ip);
#endif
return 0;
}

View File

@@ -17,8 +17,22 @@ struct pstore_ftrace_record {
#ifndef PSTORE_CPU_IN_IP
unsigned int cpu;
#endif
#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE
int pid;
unsigned long val1;
unsigned long val2;
unsigned long long time;
unsigned char comm[8];
unsigned int flag;
#endif
};
#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE
void notrace pstore_ftrace_save(struct pstore_ftrace_record *rec);
void notrace pstore_ftrace_dump(struct pstore_ftrace_record *rec,
struct seq_file *s);
#endif
static inline void
pstore_ftrace_encode_cpu(struct pstore_ftrace_record *rec, unsigned int cpu)
{

View File

@@ -602,6 +602,9 @@ static int ramoops_probe(struct platform_device *pdev)
cxt->size = pdata->mem_size;
cxt->phys_addr = pdata->mem_address;
cxt->memtype = pdata->mem_type;
#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE
cxt->memtype |= (!!ramoops_io_en);
#endif
cxt->record_size = pdata->record_size;
cxt->console_size = pdata->console_size;
cxt->ftrace_size = pdata->ftrace_size;
@@ -621,7 +624,6 @@ static int ramoops_probe(struct platform_device *pdev)
cxt->console_size, 0);
if (err)
goto fail_init_cprz;
err = ramoops_init_prz(dev, cxt, &cxt->fprz, &paddr, cxt->ftrace_size,
LINUX_VERSION_CODE);
if (err)
@@ -679,6 +681,17 @@ static int ramoops_probe(struct platform_device *pdev)
cxt->size, (unsigned long long)cxt->phys_addr,
cxt->ecc_info.ecc_size, cxt->ecc_info.block_size);
#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE
if (ramoops_ftrace_size) {
cxt->fprz->flags |= (PRZ_FLAG_NO_LOCK | PRZ_FLAG_BIG_LOCK);
ramoops_ftrace_en = !persistent_ram_old_size(cxt->fprz);
}
pr_info("ramoops_io_en:%d %d old:0x%lx ftrace_size:0x%lx",
ramoops_io_en, ramoops_ftrace_en,
(unsigned long)persistent_ram_old_size(cxt->fprz),
ramoops_ftrace_size);
#endif
return 0;
fail_buf:

View File

@@ -12,6 +12,7 @@
*
*/
#define SKIP_IO_TRACE
#define pr_fmt(fmt) "persistent_ram: " fmt
#include <linux/device.h>
@@ -49,7 +50,8 @@ static inline size_t buffer_start(struct persistent_ram_zone *prz)
}
/* increase and wrap the start pointer, returning the old value */
static size_t buffer_start_add(struct persistent_ram_zone *prz, size_t a)
static size_t notrace buffer_start_add(struct persistent_ram_zone *prz,
size_t a)
{
int old;
int new;
@@ -71,7 +73,7 @@ static size_t buffer_start_add(struct persistent_ram_zone *prz, size_t a)
}
/* increase the size counter until it hits the max size */
static void buffer_size_add(struct persistent_ram_zone *prz, size_t a)
static void notrace buffer_size_add(struct persistent_ram_zone *prz, size_t a)
{
size_t old;
size_t new;
@@ -310,6 +312,12 @@ int notrace persistent_ram_write(struct persistent_ram_zone *prz,
int c = count;
size_t start;
#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE
unsigned long flags = 0;
if (prz->flags & PRZ_FLAG_BIG_LOCK)
raw_spin_lock_irqsave(&prz->buffer_lock, flags);
#endif
if (unlikely(c > prz->buffer_size)) {
s += c - prz->buffer_size;
c = prz->buffer_size;
@@ -330,6 +338,10 @@ int notrace persistent_ram_write(struct persistent_ram_zone *prz,
persistent_ram_update_header_ecc(prz);
#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE
if (prz->flags & PRZ_FLAG_BIG_LOCK)
raw_spin_unlock_irqrestore(&prz->buffer_lock, flags);
#endif
return count;
}

View File

@@ -0,0 +1,62 @@
/*
* include/linux/amlogic/debug_ftrace_ramoops.h
*
* Copyright (C) 2017 Amlogic, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* 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 __DEBUG_FTRACE_RAMOOPS_H__
#define __DEBUG_FTRACE_RAMOOPS_H__
#define __DEBUG_FTRACE_RAMOOPS_H__
#include <linux/ftrace.h>
extern unsigned int ramoops_ftrace_en;
extern int ramoops_io_en;
extern unsigned int dump_iomap;
#define PSTORE_FLAG_FUNC 0x1
#define PSTORE_FLAG_IO_R 0x2
#define PSTORE_FLAG_IO_W 0x3
#define PSTORE_FLAG_IO_R_END 0x4
#define PSTORE_FLAG_IO_W_END 0x5
#define PSTORE_FLAG_IO_MAX 0x6
#define PSTORE_FLAG_MASK 0xF
void notrace pstore_io_save(unsigned long reg, unsigned long val,
unsigned long parant, unsigned int flag);
//#define SKIP_IO_TRACE
#if (defined CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE) && (!defined SKIP_IO_TRACE)
#define pstore_ftrace_io_wr(reg, val) \
pstore_io_save(reg, val, CALLER_ADDR0, PSTORE_FLAG_IO_W)
#define pstore_ftrace_io_wr_end(reg, val) \
pstore_io_save(reg, 0, CALLER_ADDR0, PSTORE_FLAG_IO_W_END)
#define pstore_ftrace_io_rd(reg) \
pstore_io_save(reg, 0, CALLER_ADDR0, PSTORE_FLAG_IO_R)
#define pstore_ftrace_io_rd_end(reg) \
pstore_io_save(reg, 0, CALLER_ADDR0, PSTORE_FLAG_IO_R_END)
#define need_dump_iomap() (ramoops_io_en | dump_iomap)
#else
#define pstore_ftrace_io_wr(reg, val) do { } while (0)
#define pstore_ftrace_io_rd(reg) do { } while (0)
#define need_dump_iomap() 0
#define pstore_ftrace_io_wr_end(reg, val) do { } while (0)
#define pstore_ftrace_io_rd_end(reg) do { } while (0)
#endif
#endif

View File

@@ -26,8 +26,9 @@ enum{
IO_HIUBUS_BASE,
IO_BUS_MAX,
};
extern int aml_reg_read(u32 bus_type, unsigned int reg, unsigned int *val);
extern int aml_reg_write(u32 bus_type, unsigned int reg, unsigned int val);
extern inline int aml_reg_read(u32 bus_type, u32 reg, u32 *val);
extern inline int aml_reg_write(u32 bus_type, u32 reg, u32 val);
extern int aml_regmap_update_bits(u32 bus_type,
unsigned int reg, unsigned int mask,
unsigned int val);

View File

@@ -30,6 +30,7 @@
* PRZ_FLAG_NO_LOCK is used. For all other cases, locking is required.
*/
#define PRZ_FLAG_NO_LOCK BIT(0)
#define PRZ_FLAG_BIG_LOCK BIT(7)
struct persistent_ram_buffer;
struct rs_control;

View File

@@ -12,6 +12,10 @@
#include <linux/export.h>
#include <asm/cacheflush.h>
#include <asm/pgtable.h>
#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE
#include <linux/moduleparam.h>
#include <linux/amlogic/debug_ftrace_ramoops.h>
#endif
#ifdef CONFIG_HAVE_ARCH_HUGE_VMAP
static int __read_mostly ioremap_pud_capable;
@@ -122,6 +126,19 @@ static inline int ioremap_pud_range(pgd_t *pgd, unsigned long addr,
return 0;
}
#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE
bool is_normal_memory(pgprot_t p)
{
#if defined(CONFIG_ARM)
return ((pgprot_val(p) & L_PTE_MT_MASK) == L_PTE_MT_WRITEALLOC);
#elif defined(CONFIG_ARM64)
return (pgprot_val(p) & PTE_ATTRINDX_MASK) == PTE_ATTRINDX(MT_NORMAL);
#else
#error "Unuspported architecture"
#endif
}
#endif
int ioremap_page_range(unsigned long addr,
unsigned long end, phys_addr_t phys_addr, pgprot_t prot)
{
@@ -143,7 +160,12 @@ int ioremap_page_range(unsigned long addr,
} while (pgd++, addr = next, addr != end);
flush_cache_vmap(start, end);
#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE
if (need_dump_iomap() && !is_normal_memory(prot))
pr_err("io__map <va:0x%08lx-0x%08lx> pa:0x%lx,port:0x%lx\n",
start, end, (unsigned long)phys_addr,
(unsigned long)pgprot_val(prot));
#endif
return err;
}
EXPORT_SYMBOL_GPL(ioremap_page_range);