coredump: drivers: Add coredump device
Add a pseudo device diver with device tree bindings for coredump. The device tree bindings exposes memory address/size values to be included in any dump. And the driver exposes an API to add/remove dump memory regions at runtime. Signed-off-by: Mark Holden <mholden@fb.com>
This commit is contained in:
parent
de5296203a
commit
44c388fb33
12 changed files with 480 additions and 0 deletions
|
@ -70,3 +70,4 @@ add_subdirectory_ifdef(CONFIG_MBOX mbox)
|
|||
add_subdirectory_ifdef(CONFIG_BOARD_XENVM xen)
|
||||
add_subdirectory_ifdef(CONFIG_MM_DRV mm)
|
||||
add_subdirectory_ifdef(CONFIG_RESET reset)
|
||||
add_subdirectory_ifdef(CONFIG_COREDUMP_DEVICE coredump)
|
||||
|
|
|
@ -141,4 +141,6 @@ source "drivers/reset/Kconfig"
|
|||
|
||||
source "drivers/mipi_dsi/Kconfig"
|
||||
|
||||
source "drivers/coredump/Kconfig"
|
||||
|
||||
endmenu
|
||||
|
|
6
drivers/coredump/CMakeLists.txt
Normal file
6
drivers/coredump/CMakeLists.txt
Normal file
|
@ -0,0 +1,6 @@
|
|||
# Copyright Meta Platforms, Inc. and its affiliates.
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
zephyr_library()
|
||||
|
||||
zephyr_library_sources(coredump_impl.c)
|
22
drivers/coredump/Kconfig
Normal file
22
drivers/coredump/Kconfig
Normal file
|
@ -0,0 +1,22 @@
|
|||
# Copyright Meta Platforms, Inc. and its affiliates.
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
menuconfig COREDUMP_DEVICE
|
||||
bool "Coredump pseudo-device driver"
|
||||
help
|
||||
Enable support for a pseudo-device to help capturing
|
||||
desired data into core dumps.
|
||||
|
||||
if COREDUMP_DEVICE
|
||||
|
||||
config COREDUMP_DEVICE_INIT_PRIORITY
|
||||
int "Coredump device init priority"
|
||||
default KERNEL_INIT_PRIORITY_DEVICE
|
||||
help
|
||||
Coredump pseudo-device driver initialization priority.
|
||||
|
||||
module = COREDUMP_DEVICE
|
||||
module-str = coredump device
|
||||
source "subsys/logging/Kconfig.template.log_config"
|
||||
|
||||
endif # COREDUMP_DEVICE
|
184
drivers/coredump/coredump_impl.c
Normal file
184
drivers/coredump/coredump_impl.c
Normal file
|
@ -0,0 +1,184 @@
|
|||
/*
|
||||
* Copyright Meta Platforms, Inc. and its affiliates.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <debug/coredump.h>
|
||||
#include <drivers/coredump.h>
|
||||
|
||||
#define DT_DRV_COMPAT zephyr_coredump
|
||||
|
||||
enum COREDUMP_TYPE {
|
||||
COREDUMP_TYPE_MEMCPY = 0,
|
||||
COREDUMP_TYPE_CALLBACK = 1,
|
||||
};
|
||||
|
||||
struct coredump_config {
|
||||
/* Type of coredump device */
|
||||
enum COREDUMP_TYPE type;
|
||||
|
||||
/* Length of memory_regions array */
|
||||
int length;
|
||||
|
||||
/* Memory regions specified in device tree */
|
||||
size_t memory_regions[];
|
||||
};
|
||||
|
||||
struct coredump_data {
|
||||
/* Memory regions registered at run time */
|
||||
sys_slist_t region_list;
|
||||
|
||||
/* Callback to be invoked at time of dump */
|
||||
coredump_dump_callback_t dump_callback;
|
||||
};
|
||||
|
||||
static void coredump_impl_dump(const struct device *dev)
|
||||
{
|
||||
const struct coredump_config *config = dev->config;
|
||||
struct coredump_data *data = dev->data;
|
||||
|
||||
if (config->type == COREDUMP_TYPE_CALLBACK) {
|
||||
if (data->dump_callback) {
|
||||
uintptr_t start_address = config->memory_regions[0];
|
||||
size_t size = config->memory_regions[1];
|
||||
|
||||
/* Invoke callback to allow consumer to fill array with desired data */
|
||||
data->dump_callback(start_address, size);
|
||||
coredump_memory_dump(start_address, start_address + size);
|
||||
}
|
||||
} else { /* COREDUMP_TYPE_MEMCPY */
|
||||
/*
|
||||
* Add each memory region specified in device tree to the core dump,
|
||||
* the memory_regions array should contain two entries per region
|
||||
* containing the start address and size.
|
||||
*/
|
||||
if ((config->length > 0) && ((config->length % 2) == 0)) {
|
||||
for (int i = 0; i < config->length; i += 2) {
|
||||
uintptr_t start_address = config->memory_regions[i];
|
||||
size_t size = config->memory_regions[i+1];
|
||||
|
||||
coredump_memory_dump(start_address, start_address + size);
|
||||
}
|
||||
}
|
||||
|
||||
sys_snode_t *node;
|
||||
|
||||
/* Add each memory region registered at runtime to the core dump */
|
||||
SYS_SLIST_FOR_EACH_NODE(&data->region_list, node) {
|
||||
struct coredump_mem_region_node *region;
|
||||
|
||||
region = CONTAINER_OF(node, struct coredump_mem_region_node, node);
|
||||
coredump_memory_dump(region->start, region->start + region->size);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static bool coredump_impl_register_memory(const struct device *dev,
|
||||
struct coredump_mem_region_node *region)
|
||||
{
|
||||
const struct coredump_config *config = dev->config;
|
||||
|
||||
if (config->type == COREDUMP_TYPE_CALLBACK) {
|
||||
return false;
|
||||
}
|
||||
|
||||
struct coredump_data *data = dev->data;
|
||||
|
||||
sys_slist_append(&data->region_list, ®ion->node);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool coredump_impl_unregister_memory(const struct device *dev,
|
||||
struct coredump_mem_region_node *region)
|
||||
{
|
||||
const struct coredump_config *config = dev->config;
|
||||
|
||||
if (config->type == COREDUMP_TYPE_CALLBACK) {
|
||||
return false;
|
||||
}
|
||||
|
||||
struct coredump_data *data = dev->data;
|
||||
|
||||
return sys_slist_find_and_remove(&data->region_list, ®ion->node);
|
||||
}
|
||||
|
||||
static bool coredump_impl_register_callback(const struct device *dev,
|
||||
coredump_dump_callback_t callback)
|
||||
{
|
||||
const struct coredump_config *config = dev->config;
|
||||
|
||||
if (config->type == COREDUMP_TYPE_MEMCPY) {
|
||||
return false;
|
||||
}
|
||||
|
||||
struct coredump_data *data = dev->data;
|
||||
|
||||
data->dump_callback = callback;
|
||||
return true;
|
||||
}
|
||||
|
||||
static int coredump_init(const struct device *dev)
|
||||
{
|
||||
struct coredump_data *data = dev->data;
|
||||
|
||||
sys_slist_init(&data->region_list);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct coredump_driver_api coredump_api = {
|
||||
.dump = coredump_impl_dump,
|
||||
.register_memory = coredump_impl_register_memory,
|
||||
.unregister_memory = coredump_impl_unregister_memory,
|
||||
.register_callback = coredump_impl_register_callback,
|
||||
};
|
||||
|
||||
#define INIT_REGION(node_id, prop, idx) DT_PROP_BY_IDX(node_id, prop, idx),
|
||||
#define DT_INST_COREDUMP_IF_TYPE_CALLBACK(n, a, b) \
|
||||
COND_CODE_1(DT_INST_ENUM_IDX(n, coredump_type), a, b)
|
||||
|
||||
#define CREATE_COREDUMP_DEVICE(n) \
|
||||
/* Statially allocate desired memory for the callback type device */ \
|
||||
DT_INST_COREDUMP_IF_TYPE_CALLBACK(n, \
|
||||
( \
|
||||
BUILD_ASSERT(DT_INST_PROP_LEN(n, memory_regions) == 2, \
|
||||
"Allow exactly one entry (address and size) in memory_regions"); \
|
||||
BUILD_ASSERT(DT_INST_PROP_BY_IDX(n, memory_regions, 0) == 0, \
|
||||
"Verify address is set to 0"); \
|
||||
static uint8_t coredump_bytes[DT_INST_PROP_BY_IDX(n, memory_regions, 1)] \
|
||||
__aligned(4); \
|
||||
), ()) \
|
||||
static struct coredump_data coredump_data_##n; \
|
||||
static const struct coredump_config coredump_config##n = { \
|
||||
.type = DT_INST_STRING_TOKEN_OR(n, coredump_type, COREDUMP_TYPE_MEMCPY), \
|
||||
COND_CODE_1(DT_INST_NODE_HAS_PROP(n, memory_regions), \
|
||||
( \
|
||||
.length = DT_INST_PROP_LEN(n, memory_regions), \
|
||||
DT_INST_COREDUMP_IF_TYPE_CALLBACK(n, \
|
||||
( \
|
||||
/* Callback type device has one entry in memory_regions array */ \
|
||||
.memory_regions = { \
|
||||
(size_t)&coredump_bytes[0], \
|
||||
DT_INST_PROP_BY_IDX(n, memory_regions, 1), \
|
||||
}, \
|
||||
), \
|
||||
( \
|
||||
.memory_regions = { \
|
||||
DT_INST_FOREACH_PROP_ELEM(n, memory_regions, INIT_REGION) \
|
||||
}, \
|
||||
)) \
|
||||
), \
|
||||
( \
|
||||
.length = 0, \
|
||||
)) \
|
||||
}; \
|
||||
DEVICE_DT_INST_DEFINE(n, \
|
||||
coredump_init, \
|
||||
NULL, \
|
||||
&coredump_data_##n, \
|
||||
&coredump_config##n, \
|
||||
PRE_KERNEL_1, \
|
||||
CONFIG_COREDUMP_DEVICE_INIT_PRIORITY, \
|
||||
&coredump_api);
|
||||
|
||||
DT_INST_FOREACH_STATUS_OKAY(CREATE_COREDUMP_DEVICE)
|
Loading…
Add table
Add a link
Reference in a new issue