mirror of https://github.com/thesofproject/sof.git
268 lines
8.2 KiB
C
268 lines
8.2 KiB
C
// SPDX-License-Identifier: BSD-3-Clause
|
|
//
|
|
// Copyright(c) 2016 Intel Corporation. All rights reserved.
|
|
//
|
|
// Author: Liam Girdwood <liam.r.girdwood@linux.intel.com>
|
|
// Artur Kloniecki <arturx.kloniecki@linux.intel.com>
|
|
|
|
#include <sof/debug/panic.h>
|
|
#include <sof/drivers/timer.h>
|
|
#include <sof/lib/alloc.h>
|
|
#include <sof/lib/cache.h>
|
|
#include <sof/lib/cpu.h>
|
|
#include <sof/lib/mailbox.h>
|
|
#include <sof/lib/memory.h>
|
|
#include <sof/platform.h>
|
|
#include <sof/string.h>
|
|
#include <sof/sof.h>
|
|
#include <sof/spinlock.h>
|
|
#include <sof/trace/dma-trace.h>
|
|
#include <sof/trace/preproc.h>
|
|
#include <sof/trace/trace.h>
|
|
#include <ipc/topology.h>
|
|
#include <user/trace.h>
|
|
#include <stdint.h>
|
|
|
|
/* calculates total message size, both header and payload in bytes */
|
|
#define MESSAGE_SIZE(args_num) \
|
|
(sizeof(struct log_entry_header) + args_num * sizeof(uint32_t))
|
|
|
|
/* calculated total message size in dwords */
|
|
#define MESSAGE_SIZE_DWORDS(args_num) \
|
|
(MESSAGE_SIZE(args_num) / sizeof(uint32_t))
|
|
|
|
/* calculates offset to param_idx of payload */
|
|
#define PAYLOAD_OFFSET(param_idx) \
|
|
(MESSAGE_SIZE_DWORDS(0) + param_idx)
|
|
|
|
#define TRACE_ID_MASK ((1 << TRACE_ID_LENGTH) - 1)
|
|
|
|
static void put_header(uint32_t *dst, uint32_t id_0,
|
|
uint32_t id_1, uint32_t id_2,
|
|
uint32_t entry, uint64_t timestamp)
|
|
{
|
|
struct timer *timer = timer_get();
|
|
struct log_entry_header header;
|
|
int ret;
|
|
|
|
header.uid = id_0;
|
|
header.id_0 = id_1 & TRACE_ID_MASK;
|
|
header.id_1 = id_2 & TRACE_ID_MASK;
|
|
header.core_id = cpu_get_id();
|
|
header.timestamp = timestamp + timer->delta;
|
|
header.log_entry_address = entry;
|
|
|
|
ret = memcpy_s(dst, sizeof(header), &header, sizeof(header));
|
|
assert(!ret);
|
|
|
|
platform_shared_commit(timer, sizeof(*timer));
|
|
}
|
|
|
|
static void mtrace_event(const char *data, uint32_t length)
|
|
{
|
|
struct trace *trace = trace_get();
|
|
volatile char *t;
|
|
uint32_t i, available;
|
|
|
|
available = MAILBOX_TRACE_SIZE - trace->pos;
|
|
|
|
t = (volatile char *)(MAILBOX_TRACE_BASE);
|
|
|
|
/* write until we run out of space */
|
|
for (i = 0; i < available && i < length; i++)
|
|
t[trace->pos + i] = data[i];
|
|
|
|
dcache_writeback_region((void *)&t[trace->pos], i);
|
|
trace->pos += length;
|
|
|
|
/* if there was more data than space available, wrap back */
|
|
if (length > available) {
|
|
for (i = 0; i < length - available; i++)
|
|
t[i] = data[available + i];
|
|
|
|
dcache_writeback_region((void *)t, i);
|
|
trace->pos = i;
|
|
}
|
|
|
|
platform_shared_commit(trace, sizeof(*trace));
|
|
}
|
|
|
|
#define _TRACE_EVENT_NTH_IMPL_PAYLOAD_STEP(i, _) \
|
|
dt[PAYLOAD_OFFSET(i)] = META_CONCAT(param, i);
|
|
|
|
#define _TRACE_EVENT_NTH_PAYLOAD_IMPL(arg_count) \
|
|
META_SEQ_FROM_0_TO(arg_count, _TRACE_EVENT_NTH_IMPL_PAYLOAD_STEP)
|
|
|
|
/* _trace_event function with poor people's version of constexpr if */
|
|
#define _TRACE_EVENT_NTH_IMPL(is_mbox, is_atomic, arg_count) \
|
|
_TRACE_EVENT_NTH(META_CONCAT( \
|
|
/*if is_mbox , append _mbox to function name*/ \
|
|
META_IF_ELSE(is_mbox)(_mbox)(), \
|
|
/*if is_atomic, append _atomic to function name*/ \
|
|
META_IF_ELSE(is_atomic)(_atomic)() \
|
|
), arg_count) \
|
|
{ \
|
|
uint32_t dt[MESSAGE_SIZE_DWORDS(arg_count)]; \
|
|
struct trace *trace = trace_get(); \
|
|
META_IF_ELSE(is_mbox) \
|
|
( \
|
|
META_IF_ELSE(is_atomic)()(unsigned long flags;) \
|
|
)() \
|
|
\
|
|
if (!trace->enable) { \
|
|
platform_shared_commit(trace, sizeof(*trace)); \
|
|
return; \
|
|
} \
|
|
\
|
|
put_header(dt, id_0, id_1, id_2, log_entry, \
|
|
platform_timer_get(timer_get())); \
|
|
\
|
|
_TRACE_EVENT_NTH_PAYLOAD_IMPL(arg_count) \
|
|
META_IF_ELSE(is_atomic) \
|
|
(dtrace_event_atomic) \
|
|
(dtrace_event) \
|
|
((const char *)dt, MESSAGE_SIZE(arg_count)); \
|
|
/* send event by mail box too. */ \
|
|
META_IF_ELSE(is_mbox) \
|
|
( \
|
|
META_IF_ELSE(is_atomic)()( \
|
|
spin_lock_irq(&trace->lock, flags); \
|
|
) \
|
|
mtrace_event((const char *)dt, MESSAGE_SIZE(arg_count));\
|
|
\
|
|
META_IF_ELSE(is_atomic)()(spin_unlock_irq(&trace->lock, \
|
|
flags);) \
|
|
)() \
|
|
}
|
|
|
|
#define _TRACE_EVENT_NTH_IMPL_GROUP(arg_count) \
|
|
/* send trace events only to the local trace buffer */ \
|
|
_TRACE_EVENT_NTH_IMPL(0, 0, arg_count) \
|
|
_TRACE_EVENT_NTH_IMPL(0, 1, arg_count) \
|
|
/* send trace events to the local trace buffer and mailbox */ \
|
|
_TRACE_EVENT_NTH_IMPL(1, 0, arg_count) \
|
|
_TRACE_EVENT_NTH_IMPL(1, 1, arg_count)
|
|
|
|
|
|
/* Implementation of
|
|
* void _trace_event1( uintptr_t log_entry, uint32_t ids...) {...}
|
|
* void _trace_event_mbox1( uintptr_t log_entry, uint32_t ids...) {...}
|
|
* void _trace_event_atomic1( uintptr_t log_entry, uint32_t ids...) {...}
|
|
* void _trace_event_mbox_atomic1(uintptr_t log_entry, uint32_t ids...) {...}
|
|
*/
|
|
_TRACE_EVENT_NTH_IMPL_GROUP(0)
|
|
|
|
/* Implementation of
|
|
* void _trace_event1( uintptr_t log_entry, uint32_t ids...,
|
|
* uint32_t params...) {...}
|
|
* void _trace_event_mbox1( uintptr_t log_entry, uint32_t ids...,
|
|
* uint32_t params...) {...}
|
|
* void _trace_event_atomic1( uintptr_t log_entry, uint32_t ids...,
|
|
* uint32_t params...) {...}
|
|
* void _trace_event_mbox_atomic1(uintptr_t log_entry, uint32_t ids...,
|
|
* uint32_t params...) {...}
|
|
*/
|
|
_TRACE_EVENT_NTH_IMPL_GROUP(1)
|
|
|
|
/* Implementation of
|
|
* void _trace_event2( uintptr_t log_entry, uint32_t ids...,
|
|
* uint32_t params...) {...}
|
|
* void _trace_event_mbox2( uintptr_t log_entry, uint32_t ids...,
|
|
* uint32_t params...) {...}
|
|
* void _trace_event_atomic2( uintptr_t log_entry, uint32_t ids...,
|
|
* uint32_t params...) {...}
|
|
* void _trace_event_mbox_atomic2(uintptr_t log_entry, uint32_t ids...,
|
|
* uint32_t params...) {...}
|
|
*/
|
|
_TRACE_EVENT_NTH_IMPL_GROUP(2)
|
|
|
|
/* Implementation of
|
|
* void _trace_event3( uintptr_t log_entry, uint32_t ids...,
|
|
* uint32_t params...) {...}
|
|
* void _trace_event_mbox3( uintptr_t log_entry, uint32_t ids...,
|
|
* uint32_t params...) {...}
|
|
* void _trace_event_atomic3( uintptr_t log_entry, uint32_t ids...,
|
|
* uint32_t params...) {...}
|
|
* void _trace_event_mbox_atomic3(uintptr_t log_entry, uint32_t ids...,
|
|
* uint32_t params...) {...}
|
|
*/
|
|
_TRACE_EVENT_NTH_IMPL_GROUP(3)
|
|
|
|
/* Implementation of
|
|
* void _trace_event4( uintptr_t log_entry, uint32_t ids...,
|
|
* uint32_t params...) {...}
|
|
* void _trace_event_mbox4( uintptr_t log_entry, uint32_t ids...,
|
|
* uint32_t params...) {...}
|
|
* void _trace_event_atomic4( uintptr_t log_entry, uint32_t ids...,
|
|
* uint32_t params...) {...}
|
|
* void _trace_event_mbox_atomic4(uintptr_t log_entry, uint32_t ids...,
|
|
* uint32_t params...) {...}
|
|
*/
|
|
_TRACE_EVENT_NTH_IMPL_GROUP(4)
|
|
|
|
void trace_flush(void)
|
|
{
|
|
struct trace *trace = trace_get();
|
|
volatile uint64_t *t;
|
|
uint32_t flags;
|
|
|
|
spin_lock_irq(&trace->lock, flags);
|
|
|
|
/* get mailbox position */
|
|
t = (volatile uint64_t *)(MAILBOX_TRACE_BASE + trace->pos);
|
|
|
|
/* flush dma trace messages */
|
|
dma_trace_flush((void *)t);
|
|
|
|
platform_shared_commit(trace, sizeof(*trace));
|
|
|
|
spin_unlock_irq(&trace->lock, flags);
|
|
}
|
|
|
|
void trace_on(void)
|
|
{
|
|
struct trace *trace = trace_get();
|
|
uint32_t flags;
|
|
|
|
spin_lock_irq(&trace->lock, flags);
|
|
|
|
trace->enable = 1;
|
|
dma_trace_on();
|
|
|
|
platform_shared_commit(trace, sizeof(*trace));
|
|
|
|
spin_unlock_irq(&trace->lock, flags);
|
|
}
|
|
|
|
void trace_off(void)
|
|
{
|
|
struct trace *trace = trace_get();
|
|
uint32_t flags;
|
|
|
|
spin_lock_irq(&trace->lock, flags);
|
|
|
|
trace->enable = 0;
|
|
dma_trace_off();
|
|
|
|
platform_shared_commit(trace, sizeof(*trace));
|
|
|
|
spin_unlock_irq(&trace->lock, flags);
|
|
}
|
|
|
|
void trace_init(struct sof *sof)
|
|
{
|
|
dma_trace_init_early(sof);
|
|
|
|
sof->trace = rzalloc(SOF_MEM_ZONE_SYS, SOF_MEM_FLAG_SHARED,
|
|
SOF_MEM_CAPS_RAM, sizeof(*sof->trace));
|
|
sof->trace->enable = 1;
|
|
sof->trace->pos = 0;
|
|
spinlock_init(&sof->trace->lock);
|
|
|
|
platform_shared_commit(sof->trace, sizeof(*sof->trace));
|
|
|
|
bzero((void *)MAILBOX_TRACE_BASE, MAILBOX_TRACE_SIZE);
|
|
dcache_writeback_invalidate_region((void *)MAILBOX_TRACE_BASE,
|
|
MAILBOX_TRACE_SIZE);
|
|
}
|