diff options
Diffstat (limited to 'plat/common')
-rw-r--r-- | plat/common/aarch64/crash_console_helpers.S | 11 | ||||
-rw-r--r-- | plat/common/plat_psci_common.c | 8 | ||||
-rw-r--r-- | plat/common/plat_spm_rd.c | 316 | ||||
-rw-r--r-- | plat/common/plat_spm_sp.c | 93 | ||||
-rw-r--r-- | plat/common/ubsan.c | 220 |
5 files changed, 235 insertions, 413 deletions
diff --git a/plat/common/aarch64/crash_console_helpers.S b/plat/common/aarch64/crash_console_helpers.S index 2a48baf0a..e2950f5f7 100644 --- a/plat/common/aarch64/crash_console_helpers.S +++ b/plat/common/aarch64/crash_console_helpers.S @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -125,9 +125,18 @@ putc_loop: b.eq putc_continue ldr x2, [x15, #CONSOLE_T_PUTC] cbz x2, putc_continue + cmp w14, #'\n' + b.ne putc + tst w1, #CONSOLE_FLAG_TRANSLATE_CRLF + b.eq putc mov x1, x15 + mov w0, #'\r' blr x2 + ldr x2, [x15, #CONSOLE_T_PUTC] +putc: + mov x1, x15 mov w0, w14 + blr x2 putc_continue: ldr x15, [x15] /* X15 = next struct */ b putc_loop diff --git a/plat/common/plat_psci_common.c b/plat/common/plat_psci_common.c index 16bec7972..80ed8198b 100644 --- a/plat/common/plat_psci_common.c +++ b/plat/common/plat_psci_common.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2016-2019, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -31,6 +31,8 @@ #define PSCI_STAT_ID_EXIT_LOW_PWR 1 #define PSCI_STAT_TOTAL_IDS 2 +PMF_DECLARE_CAPTURE_TIMESTAMP(psci_svc) +PMF_DECLARE_GET_TIMESTAMP(psci_svc) PMF_REGISTER_SERVICE(psci_svc, PMF_PSCI_STAT_SVC_ID, PSCI_STAT_TOTAL_IDS, PMF_STORE_ENABLE) @@ -92,7 +94,7 @@ void plat_psci_stat_accounting_stop( */ u_register_t plat_psci_stat_get_residency(unsigned int lvl, const psci_power_state_t *state_info, - int last_cpu_idx) + unsigned int last_cpu_idx) { plat_local_state_t state; unsigned long long pwrup_ts = 0, pwrdn_ts = 0; @@ -103,7 +105,7 @@ u_register_t plat_psci_stat_get_residency(unsigned int lvl, assert(last_cpu_idx <= PLATFORM_CORE_COUNT); if (lvl == PSCI_CPU_PWR_LVL) - assert((unsigned int)last_cpu_idx == plat_my_core_pos()); + assert(last_cpu_idx == plat_my_core_pos()); /* * If power down is requested, then timestamp capture will diff --git a/plat/common/plat_spm_rd.c b/plat/common/plat_spm_rd.c deleted file mode 100644 index ebd3e6dc6..000000000 --- a/plat/common/plat_spm_rd.c +++ /dev/null @@ -1,316 +0,0 @@ -/* - * Copyright (c) 2018-2019, Arm Limited. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - */ - -#include <assert.h> -#include <string.h> - -#include <libfdt.h> - -#include <platform_def.h> - -#include <common/debug.h> -#include <common/fdt_wrappers.h> -#include <lib/object_pool.h> -#include <plat/common/platform.h> -#include <services/sp_res_desc.h> - -/******************************************************************************* - * Resource pool - ******************************************************************************/ -static struct sp_rd_sect_mem_region rd_mem_regions[PLAT_SPM_MEM_REGIONS_MAX]; -static OBJECT_POOL_ARRAY(rd_mem_regions_pool, rd_mem_regions); - -static struct sp_rd_sect_notification rd_notifs[PLAT_SPM_NOTIFICATIONS_MAX]; -static OBJECT_POOL_ARRAY(rd_notifs_pool, rd_notifs); - -static struct sp_rd_sect_service rd_services[PLAT_SPM_SERVICES_MAX]; -static OBJECT_POOL_ARRAY(rd_services_pool, rd_services); - -/******************************************************************************* - * Attribute section handler - ******************************************************************************/ -static void rd_parse_attribute(struct sp_rd_sect_attribute *attr, - const void *fdt, int node) -{ - int rc = 0; - - /* The minimum size that can be read from the DTB is 32-bit. */ - uint32_t version, sp_type, runtime_el, exec_type; - uint32_t panic_policy, xlat_granule; - - rc |= fdtw_read_cells(fdt, node, "version", 1, &version); - - if (version != 1) { - ERROR("Unsupported resource description version: 0x%x\n", - version); - panic(); - } - - rc |= fdtw_read_cells(fdt, node, "sp_type", 1, &sp_type); - rc |= fdtw_read_cells(fdt, node, "pe_mpidr", 1, &attr->pe_mpidr); - rc |= fdtw_read_cells(fdt, node, "runtime_el", 1, &runtime_el); - rc |= fdtw_read_cells(fdt, node, "exec_type", 1, &exec_type); - rc |= fdtw_read_cells(fdt, node, "panic_policy", 1, &panic_policy); - rc |= fdtw_read_cells(fdt, node, "xlat_granule", 1, &xlat_granule); - rc |= fdtw_read_cells(fdt, node, "binary_size", 1, &attr->binary_size); - rc |= fdtw_read_cells(fdt, node, "load_address", 2, &attr->load_address); - rc |= fdtw_read_cells(fdt, node, "entrypoint", 2, &attr->entrypoint); - - attr->version = version; - attr->sp_type = sp_type; - attr->runtime_el = runtime_el; - attr->exec_type = exec_type; - attr->panic_policy = panic_policy; - attr->xlat_granule = xlat_granule; - - VERBOSE(" Attribute Section:\n"); - VERBOSE(" version: 0x%x\n", version); - VERBOSE(" sp_type: 0x%x\n", sp_type); - VERBOSE(" pe_mpidr: 0x%x\n", attr->pe_mpidr); - VERBOSE(" runtime_el: 0x%x\n", runtime_el); - VERBOSE(" exec_type: 0x%x\n", exec_type); - VERBOSE(" panic_policy: 0x%x\n", panic_policy); - VERBOSE(" xlat_granule: 0x%x\n", xlat_granule); - VERBOSE(" binary_size: 0x%x\n", attr->binary_size); - VERBOSE(" load_address: 0x%llx\n", attr->load_address); - VERBOSE(" entrypoint: 0x%llx\n", attr->entrypoint); - - if (rc) { - ERROR("Failed to read attribute node elements.\n"); - panic(); - } -} - -/******************************************************************************* - * Memory regions section handlers - ******************************************************************************/ -static void rd_parse_memory_region(struct sp_rd_sect_mem_region *rdmem, - const void *fdt, int node) -{ - int rc = 0; - char name[RD_MEM_REGION_NAME_LEN]; - - rc |= fdtw_read_string(fdt, node, "str", (char *)&name, sizeof(name)); - rc |= fdtw_read_cells(fdt, node, "attr", 1, &rdmem->attr); - rc |= fdtw_read_cells(fdt, node, "base", 2, &rdmem->base); - rc |= fdtw_read_cells(fdt, node, "size", 2, &rdmem->size); - - size_t len = strlcpy(rdmem->name, name, RD_MEM_REGION_NAME_LEN); - - if (len >= RD_MEM_REGION_NAME_LEN) { - WARN("Memory region name truncated: '%s'\n", name); - } - - VERBOSE(" Memory Region:\n"); - VERBOSE(" name: '%s'\n", rdmem->name); - VERBOSE(" attr: 0x%x\n", rdmem->attr); - VERBOSE(" base: 0x%llx\n", rdmem->base); - VERBOSE(" size: 0x%llx\n", rdmem->size); - - if (rc) { - ERROR("Failed to read mem_region node elements.\n"); - panic(); - } -} - -static void rd_parse_memory_regions(struct sp_res_desc *rd, const void *fdt, - int node) -{ - int child; - struct sp_rd_sect_mem_region *rdmem, *old_rdmem; - - fdt_for_each_subnode(child, fdt, node) { - rdmem = pool_alloc(&rd_mem_regions_pool); - - /* Add element to the start of the list */ - old_rdmem = rd->mem_region; - rd->mem_region = rdmem; - rdmem->next = old_rdmem; - - rd_parse_memory_region(rdmem, fdt, child); - } - - if ((child < 0) && (child != -FDT_ERR_NOTFOUND)) { - ERROR("%d: fdt_for_each_subnode(): %d\n", __LINE__, node); - panic(); - } -} - -/******************************************************************************* - * Notifications section handlers - ******************************************************************************/ -static void rd_parse_notification(struct sp_rd_sect_notification *rdnot, - const void *fdt, int node) -{ - int rc = 0; - - rc |= fdtw_read_cells(fdt, node, "attr", 1, &rdnot->attr); - rc |= fdtw_read_cells(fdt, node, "pe", 1, &rdnot->pe); - - VERBOSE(" Notification:\n"); - VERBOSE(" attr: 0x%x\n", rdnot->attr); - VERBOSE(" pe: 0x%x\n", rdnot->pe); - - if (rc) { - ERROR("Failed to read notification node elements.\n"); - panic(); - } -} - -static void rd_parse_notifications(struct sp_res_desc *rd, const void *fdt, int node) -{ - int child; - struct sp_rd_sect_notification *rdnot, *old_rdnot; - - fdt_for_each_subnode(child, fdt, node) { - rdnot = pool_alloc(&rd_notifs_pool); - - /* Add element to the start of the list */ - old_rdnot = rd->notification; - rd->notification = rdnot; - rdnot->next = old_rdnot; - - rd_parse_notification(rdnot, fdt, child); - } - - if ((child < 0) && (child != -FDT_ERR_NOTFOUND)) { - ERROR("%d: fdt_for_each_subnode(): %d\n", __LINE__, child); - panic(); - } -} - -/******************************************************************************* - * Services section handlers - ******************************************************************************/ -static void rd_parse_service(struct sp_rd_sect_service *rdsvc, const void *fdt, - int node) -{ - int rc = 0; - - /* The minimum size that can be read from the DTB is 32-bit. */ - uint32_t accessibility, request_type, connection_quota; - - rc |= fdtw_read_array(fdt, node, "uuid", 4, &rdsvc->uuid); - rc |= fdtw_read_cells(fdt, node, "accessibility", 1, &accessibility); - rc |= fdtw_read_cells(fdt, node, "request_type", 1, &request_type); - rc |= fdtw_read_cells(fdt, node, "connection_quota", 1, &connection_quota); - rc |= fdtw_read_cells(fdt, node, "sec_mem_size", 1, &rdsvc->secure_mem_size); - rc |= fdtw_read_cells(fdt, node, "interrupt_num", 1, &rdsvc->interrupt_num); - - rdsvc->accessibility = accessibility; - rdsvc->request_type = request_type; - rdsvc->connection_quota = connection_quota; - - VERBOSE(" Service:\n"); - VERBOSE(" uuid: 0x%08x 0x%08x 0x%08x 0x%08x\n", rdsvc->uuid[0], - rdsvc->uuid[1], rdsvc->uuid[2], rdsvc->uuid[3]); - VERBOSE(" accessibility: 0x%x\n", accessibility); - VERBOSE(" request_type: 0x%x\n", request_type); - VERBOSE(" connection_quota: 0x%x\n", connection_quota); - VERBOSE(" secure_memory_size: 0x%x\n", rdsvc->secure_mem_size); - VERBOSE(" interrupt_num: 0x%x\n", rdsvc->interrupt_num); - - if (rc) { - ERROR("Failed to read attribute node elements.\n"); - panic(); - } -} - -static void rd_parse_services(struct sp_res_desc *rd, const void *fdt, int node) -{ - int child; - struct sp_rd_sect_service *rdsvc, *old_rdsvc; - - fdt_for_each_subnode(child, fdt, node) { - rdsvc = pool_alloc(&rd_services_pool); - - /* Add element to the start of the list */ - old_rdsvc = rd->service; - rd->service = rdsvc; - rdsvc->next = old_rdsvc; - - rd_parse_service(rdsvc, fdt, child); - } - - if ((child < 0) && (child != -FDT_ERR_NOTFOUND)) { - ERROR("%d: fdt_for_each_subnode(): %d\n", __LINE__, node); - panic(); - } -} - -/******************************************************************************* - * Root node handler - ******************************************************************************/ -static void rd_parse_root(struct sp_res_desc *rd, const void *fdt, int root) -{ - int node; - char *str; - - str = "attribute"; - node = fdt_subnode_offset_namelen(fdt, root, str, strlen(str)); - if (node < 0) { - ERROR("Root node doesn't contain subnode '%s'\n", str); - panic(); - } else { - rd_parse_attribute(&rd->attribute, fdt, node); - } - - str = "memory_regions"; - node = fdt_subnode_offset_namelen(fdt, root, str, strlen(str)); - if (node < 0) { - ERROR("Root node doesn't contain subnode '%s'\n", str); - panic(); - } else { - rd_parse_memory_regions(rd, fdt, node); - } - - str = "notifications"; - node = fdt_subnode_offset_namelen(fdt, root, str, strlen(str)); - if (node < 0) { - WARN("Root node doesn't contain subnode '%s'\n", str); - } else { - rd_parse_notifications(rd, fdt, node); - } - - str = "services"; - node = fdt_subnode_offset_namelen(fdt, root, str, strlen(str)); - if (node < 0) { - WARN("Root node doesn't contain subnode '%s'\n", str); - } else { - rd_parse_services(rd, fdt, node); - } -} - -/******************************************************************************* - * Platform handler to load resource descriptor blobs into the active Secure - * Partition context. - ******************************************************************************/ -int plat_spm_sp_rd_load(struct sp_res_desc *rd, const void *ptr, size_t size) -{ - int rc; - int root_node; - - assert(rd != NULL); - assert(ptr != NULL); - - INFO("Reading RD blob at address %p\n", ptr); - - rc = fdt_check_header(ptr); - if (rc != 0) { - ERROR("Wrong format for resource descriptor blob (%d).\n", rc); - return -1; - } - - root_node = fdt_node_offset_by_compatible(ptr, -1, "arm,sp_rd"); - if (root_node < 0) { - ERROR("Unrecognized resource descriptor blob (%d)\n", rc); - return -1; - } - - rd_parse_root(rd, ptr, root_node); - - return 0; -} diff --git a/plat/common/plat_spm_sp.c b/plat/common/plat_spm_sp.c deleted file mode 100644 index bc3d6a015..000000000 --- a/plat/common/plat_spm_sp.c +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Copyright (c) 2018-2019, Arm Limited. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - */ - -#include <assert.h> - -#include <platform_def.h> - -#include <common/debug.h> -#include <plat/common/platform.h> -#include <tools_share/sptool.h> - -static unsigned int sp_next; - -/******************************************************************************* - * Platform handler get the address of a Secure Partition and its resource - * description blob. It iterates through all SPs detected by the platform. If - * there is information for another SP, it returns 0. If there are no more SPs, - * it returns -1. - ******************************************************************************/ -int plat_spm_sp_get_next_address(void **sp_base, size_t *sp_size, - void **rd_base, size_t *rd_size) -{ - assert((sp_base != NULL) && (sp_size != NULL)); - assert((rd_base != NULL) && (rd_base != NULL)); - - const uint64_t *pkg_base = (uint64_t *)PLAT_SP_PACKAGE_BASE; - - struct sp_pkg_header *pkg_header = (struct sp_pkg_header *)pkg_base; - - if (sp_next == 0) { - if (pkg_header->version != 0x1) { - ERROR("SP package has an unsupported version 0x%llx\n", - pkg_header->version); - panic(); - } - } - - if (sp_next >= pkg_header->number_of_sp) { - /* No more partitions in the package */ - return -1; - } - - const struct sp_pkg_entry *entry_list = - (const struct sp_pkg_entry *)((uintptr_t)pkg_base - + sizeof(struct sp_pkg_header)); - - const struct sp_pkg_entry *entry = &(entry_list[sp_next]); - - uint64_t sp_offset = entry->sp_offset; - uint64_t rd_offset = entry->rd_offset; - - uintptr_t pkg_sp_base = ((uintptr_t)PLAT_SP_PACKAGE_BASE + sp_offset); - uintptr_t pkg_rd_base = ((uintptr_t)PLAT_SP_PACKAGE_BASE + rd_offset); - - uint64_t pkg_sp_size = entry->sp_size; - uint64_t pkg_rd_size = entry->rd_size; - - uintptr_t pkg_end = (uintptr_t)PLAT_SP_PACKAGE_BASE - + (uintptr_t)PLAT_SP_PACKAGE_SIZE - 1U; - - /* - * Check for overflows. The package header isn't trusted, so assert() - * can't be used here. - */ - - uintptr_t pkg_sp_end = pkg_sp_base + pkg_sp_size - 1U; - uintptr_t pkg_rd_end = pkg_rd_base + pkg_rd_size - 1U; - - if ((pkg_sp_end > pkg_end) || (pkg_sp_end < pkg_sp_base)) { - ERROR("Invalid Secure Partition size (0x%llx)\n", pkg_sp_size); - panic(); - } - - if ((pkg_rd_end > pkg_end) || (pkg_rd_end < pkg_rd_base)) { - ERROR("Invalid Resource Description blob size (0x%llx)\n", - pkg_rd_size); - panic(); - } - - /* Return location of the binaries. */ - - *sp_base = (void *)pkg_sp_base; - *sp_size = pkg_sp_size; - *rd_base = (void *)pkg_rd_base; - *rd_size = pkg_rd_size; - - sp_next++; - - return 0; -} diff --git a/plat/common/ubsan.c b/plat/common/ubsan.c new file mode 100644 index 000000000..45b0f7cce --- /dev/null +++ b/plat/common/ubsan.c @@ -0,0 +1,220 @@ +/* + * Copyright (c) 2016, Linaro Limited + * Copyright (c) 2019, ARM Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include <arch_helpers.h> +#include <context.h> +#include <common/debug.h> +#include <plat/common/platform.h> + +struct source_location { + const char *file_name; + uint32_t line; + uint32_t column; +}; + +struct type_descriptor { + uint16_t type_kind; + uint16_t type_info; + char type_name[1]; +}; + +struct type_mismatch_data { + struct source_location loc; + struct type_descriptor *type; + unsigned long alignment; + unsigned char type_check_kind; +}; + +struct overflow_data { + struct source_location loc; + struct type_descriptor *type; +}; + +struct shift_out_of_bounds_data { + struct source_location loc; + struct type_descriptor *lhs_type; + struct type_descriptor *rhs_type; +}; + +struct out_of_bounds_data { + struct source_location loc; + struct type_descriptor *array_type; + struct type_descriptor *index_type; +}; + +struct unreachable_data { + struct source_location loc; +}; + +struct vla_bound_data { + struct source_location loc; + struct type_descriptor *type; +}; + +struct invalid_value_data { + struct source_location loc; + struct type_descriptor *type; +}; + +struct nonnull_arg_data { + struct source_location loc; +}; + +/* + * When compiling with -fsanitize=undefined the compiler expects functions + * with the following signatures. The functions are never called directly, + * only when undefined behavior is detected in instrumented code. + */ +void __ubsan_handle_type_mismatch_abort(struct type_mismatch_data *data, + unsigned long ptr); +void __ubsan_handle_type_mismatch_v1_abort(struct type_mismatch_data *data, + unsigned long ptr); +void __ubsan_handle_add_overflow_abort(struct overflow_data *data, + unsigned long lhs, unsigned long rhs); +void __ubsan_handle_sub_overflow_abort(struct overflow_data *data, + unsigned long lhs, unsigned long rhs); +void __ubsan_handle_mul_overflow_abort(struct overflow_data *data, + unsigned long lhs, unsigned long rhs); +void __ubsan_handle_negate_overflow_abort(struct overflow_data *data, + unsigned long old_val); +void __ubsan_handle_pointer_overflow_abort(struct overflow_data *data, + unsigned long old_val); +void __ubsan_handle_divrem_overflow_abort(struct overflow_data *data, + unsigned long lhs, unsigned long rhs); +void __ubsan_handle_shift_out_of_bounds_abort(struct shift_out_of_bounds_data *data, + unsigned long lhs, unsigned long rhs); +void __ubsan_handle_out_of_bounds_abort(struct out_of_bounds_data *data, + unsigned long idx); +void __ubsan_handle_unreachable_abort(struct unreachable_data *data); +void __ubsan_handle_missing_return_abort(struct unreachable_data *data); +void __ubsan_handle_vla_bound_not_positive_abort(struct vla_bound_data *data, + unsigned long bound); +void __ubsan_handle_load_invalid_value_abort(struct invalid_value_data *data, + unsigned long val); +void __ubsan_handle_nonnull_arg_abort(struct nonnull_arg_data *data +#if __GCC_VERSION < 60000 + , size_t arg_no +#endif + ); + +static void print_loc(const char *func, struct source_location *loc) +{ + ERROR("Undefined behavior at %s:%d col %d (%s)", + loc->file_name, loc->line, loc->column, func); +} + + +void __ubsan_handle_type_mismatch_abort(struct type_mismatch_data *data, + unsigned long ptr __unused) +{ + print_loc(__func__, &data->loc); + plat_panic_handler(); +} + +void __ubsan_handle_type_mismatch_v1_abort(struct type_mismatch_data *data, + unsigned long ptr __unused) +{ + print_loc(__func__, &data->loc); + plat_panic_handler(); +} + +void __ubsan_handle_add_overflow_abort(struct overflow_data *data, + unsigned long lhs __unused, + unsigned long rhs __unused) +{ + print_loc(__func__, &data->loc); + plat_panic_handler(); +} + +void __ubsan_handle_sub_overflow_abort(struct overflow_data *data, + unsigned long lhs __unused, + unsigned long rhs __unused) +{ + print_loc(__func__, &data->loc); + plat_panic_handler(); +} + +void __ubsan_handle_mul_overflow_abort(struct overflow_data *data, + unsigned long lhs __unused, + unsigned long rhs __unused) +{ + print_loc(__func__, &data->loc); + plat_panic_handler(); +} + +void __ubsan_handle_negate_overflow_abort(struct overflow_data *data, + unsigned long old_val __unused) +{ + print_loc(__func__, &data->loc); + plat_panic_handler(); +} + +void __ubsan_handle_pointer_overflow_abort(struct overflow_data *data, + unsigned long old_val __unused) +{ + print_loc(__func__, &data->loc); + plat_panic_handler(); +} + +void __ubsan_handle_divrem_overflow_abort(struct overflow_data *data, + unsigned long lhs __unused, + unsigned long rhs __unused) +{ + print_loc(__func__, &data->loc); + plat_panic_handler(); +} + +void __ubsan_handle_shift_out_of_bounds_abort(struct shift_out_of_bounds_data *data, + unsigned long lhs __unused, + unsigned long rhs __unused) +{ + print_loc(__func__, &data->loc); + plat_panic_handler(); +} + +void __ubsan_handle_out_of_bounds_abort(struct out_of_bounds_data *data, + unsigned long idx __unused) +{ + print_loc(__func__, &data->loc); + plat_panic_handler(); +} + +void __ubsan_handle_unreachable_abort(struct unreachable_data *data) +{ + print_loc(__func__, &data->loc); + plat_panic_handler(); +} + +void __ubsan_handle_missing_return_abort(struct unreachable_data *data) +{ + print_loc(__func__, &data->loc); + plat_panic_handler(); +} + +void __ubsan_handle_vla_bound_not_positive_abort(struct vla_bound_data *data, + unsigned long bound __unused) +{ + print_loc(__func__, &data->loc); + plat_panic_handler(); +} + +void __ubsan_handle_load_invalid_value_abort(struct invalid_value_data *data, + unsigned long val __unused) +{ + print_loc(__func__, &data->loc); + plat_panic_handler(); +} + +void __ubsan_handle_nonnull_arg_abort(struct nonnull_arg_data *data +#if __GCC_VERSION < 60000 + , size_t arg_no __unused +#endif + ) +{ + print_loc(__func__, &data->loc); + plat_panic_handler(); +} |