<commit_before>/*
 * Copyright (c) 2014 Wind River Systems, Inc.
 *
 * SPDX-License-Identifier: Apache-2.0
 */

/**
 * @file
 * @brief Common fault handler for ARM Cortex-M
 *
 * Common fault handler for ARM Cortex-M processors.
 */

#include <toolchain.h>
#include <linker/sections.h>

#include <kernel.h>
#include <kernel_structs.h>
#include <inttypes.h>

#ifdef CONFIG_PRINTK
#include <misc/printk.h>
#define PR_EXC(...) printk(__VA_ARGS__)
#define STORE_xFAR(reg_var, reg) u32_t reg_var = (u32_t)reg
#else
#define PR_EXC(...)
#define STORE_xFAR(reg_var, reg)
#endif /* CONFIG_PRINTK */

#if (CONFIG_FAULT_DUMP > 0)
#define FAULT_DUMP(esf, fault) _FaultDump(esf, fault)
#else
#define FAULT_DUMP(esf, fault) \
	do {                   \
		(void) esf;    \
		(void) fault;  \
	} while ((0))
#endif

#if (CONFIG_FAULT_DUMP == 1)
/**
 *
 * @brief Dump information regarding fault (FAULT_DUMP == 1)
 *
 * Dump information regarding the fault when CONFIG_FAULT_DUMP is set to 1
 * (short form).
 *
 * eg. (precise bus error escalated to hard fault):
 *
 * Fault! EXC #3, Thread: 0x200000dc, instr: 0x000011d3
 * HARD FAULT: Escalation (see below)!
 * MMFSR: 0x00000000, BFSR: 0x00000082, UFSR: 0x00000000
 * BFAR: 0xff001234
 *
 * @return N/A
 */
void _FaultDump(const NANO_ESF *esf, int fault)
{
	PR_EXC("Fault! EXC #%d, Thread: %p, instr @ 0x%x\n",
	       fault,
	       k_current_get(),
	       esf->pc);

#if defined(CONFIG_ARMV6_M_ARMV8_M_BASELINE)
#elif defined(CONFIG_ARMV7_M_ARMV8_M_MAINLINE)
	int escalation = 0;

	if (3 == fault) { /* hard fault */
		escalation = SCB->HFSR & SCB_HFSR_FORCED_Msk;
		PR_EXC("HARD FAULT: %s\n",
		       escalation ? "Escalation (see below)!"
				  : "Bus fault on vector table read\n");
	}

	PR_EXC("MMFSR: 0x%x, BFSR: 0x%x, UFSR: 0x%x\n",
	       SCB_MMFSR, SCB_BFSR, SCB_MMFSR);

	/* In a fault handler, to determine the true faulting address:
	 * 1. Read and save the MMFAR or BFAR value.
	 * 2. Read the MMARVALID bit in the MMFSR, or the BFARVALID bit in the
	 * BFSR. The MMFAR or BFAR address is valid only if this bit is 1.
	 *
	 * Software must follow this sequence because another higher priority
	 * exception might change the MMFAR or BFAR value.
	 */
	STORE_xFAR(mmfar, SCB->MMFAR);
	STORE_xFAR(bfar, SCB->BFAR);

	if (SCB->CFSR & CFSR_MMARVALID_Msk) {
		PR_EXC("MMFAR: 0x%x\n", mmfar);
		if (escalation) {
			/* clear MMAR[VALID] to reset */
			SCB->CFSR &= ~CFSR_MMARVALID_Msk;
		}
	}
	if (SCB->CFSR & CFSR_BFARVALID_Msk) {
		PR_EXC("BFAR: 0x%x\n", bfar);
		if (escalation) {
			/* clear CFSR_BFAR[VALID] to reset */
			SCB->CFSR &= ~CFSR_BFARVALID_Msk;
		}
	}

	/* clear USFR sticky bits */
	SCB->CFSR |= SCB_CFSR_USGFAULTSR_Msk;
#else
#error Unknown ARM architecture
#endif /* CONFIG_ARMV6_M_ARMV8_M_BASELINE */
}
#endif

#if (CONFIG_FAULT_DUMP == 2)
/**
 *
 * @brief Dump thread information
 *
 * See _FaultDump() for example.
 *
 * @return N/A
 */
static void _FaultThreadShow(const NANO_ESF *esf)
{
	PR_EXC("  Executing thread ID (thread): %p\n"
	       "  Faulting instruction address:  0x%x\n",
	       k_current_get(), esf->pc);
}

#if defined(CONFIG_ARMV6_M_ARMV8_M_BASELINE)
/* HardFault is used for all fault conditions on ARMv6-M. */
#elif defined(CONFIG_ARMV7_M_ARMV8_M_MAINLINE)

/**
 *
 * @brief Dump MPU fault information
 *
 * See _FaultDump() for example.
 *
 * @return N/A
 */
static void _MpuFault(const NANO_ESF *esf, int fromHardFault)
{
	PR_EXC("***** MPU FAULT *****\n");

	_FaultThreadShow(esf);

	if (SCB->CFSR & SCB_CFSR_MSTKERR_Msk) {
		PR_EXC("  Stacking error\n");
	} else if (SCB->CFSR & SCB_CFSR_MUNSTKERR_Msk) {
		PR_EXC("  Unstacking error\n");
	} else if (SCB->CFSR & SCB_CFSR_DACCVIOL_Msk) {
		PR_EXC("  Data Access Violation\n");
		/* In a fault handler, to determine the true faulting address:
		 * 1. Read and save the MMFAR value.
		 * 2. Read the MMARVALID bit in the MMFSR.
		 * The MMFAR address is valid only if this bit is 1.
		 *
		 * Software must follow this sequence because another higher
		 * priority exception might change the MMFAR value.
		 */
		STORE_xFAR(mmfar, SCB->MMFAR);

		if (SCB->CFSR & SCB_CFSR_MMARVALID_Msk) {
			PR_EXC("  Address: 0x%x\n", mmfar);
			if (fromHardFault) {
				/* clear SCB_MMAR[VALID] to reset */
				SCB->CFSR &= ~SCB_CFSR_MMARVALID_Msk;
			}
		}
	} else if (SCB->CFSR & SCB_CFSR_IACCVIOL_Msk) {
		PR_EXC("  Instruction Access Violation\n");
#if !defined(CONFIG_ARMV7_M_ARMV8_M_FP)
	}
#else
	} else if (SCB->CFSR & SCB_CFSR_MLSPERR_Msk) {
		PR_EXC("  Floating-point lazy state preservation error\n");
	}
#endif /* !defined(CONFIG_ARMV7_M_ARMV8_M_FP) */
}

/**
 *
 * @brief Dump bus fault information
 *
 * See _FaultDump() for example.
 *
 * @return N/A
 */
static void _BusFault(const NANO_ESF *esf, int fromHardFault)
{
	PR_EXC("***** BUS FAULT *****\n");

	_FaultThreadShow(esf);

	if (SCB->CFSR & SCB_CFSR_STKERR_Msk) {
		PR_EXC("  Stacking error\n");
	} else if (SCB->CFSR & SCB_CFSR_UNSTKERR_Msk) {
		PR_EXC("  Unstacking error\n");
	} else if (SCB->CFSR & SCB_CFSR_PRECISERR_Msk) {
		PR_EXC("  Precise data bus error\n");
		/* In a fault handler, to determine the true faulting address:
		 * 1. Read and save the BFAR value.
		 * 2. Read the BFARVALID bit in the BFSR.
		 * The BFAR address is valid only if this bit is 1.
		 *
		 * Software must follow this sequence because another
		 * higher priority exception might change the BFAR value.
		 */
		STORE_xFAR(bfar, SCB->BFAR);

		if (SCB->CFSR & SCB_CFSR_BFARVALID_Msk) {
			PR_EXC("  Address: 0x%x\n", bfar);
			if (fromHardFault) {
				/* clear SCB_CFSR_BFAR[VALID] to reset */
				SCB->CFSR &= ~SCB_CFSR_BFARVALID_Msk;
			}
		}
		/* it's possible to have both a precise and imprecise fault */
		if (SCB->CFSR & SCB_CFSR_IMPRECISERR_Msk) {
			PR_EXC("  Imprecise data bus error\n");
		}
	} else if (SCB->CFSR & SCB_CFSR_IMPRECISERR_Msk) {
		PR_EXC("  Imprecise data bus error\n");
	} else if (SCB->CFSR & SCB_CFSR_IBUSERR_Msk) {
		PR_EXC("  Instruction bus error\n");
#if !defined(CONFIG_ARMV7_M_ARMV8_M_FP)
	}
#else
	} else if (SCB->CFSR & SCB_CFSR_LSPERR_Msk) {
		PR_EXC("  Floating-point lazy state preservation error\n");
	}
#endif /* !defined(CONFIG_ARMV7_M_ARMV8_M_FP) */
}

/**
 *
 * @brief Dump usage fault information
 *
 * See _FaultDump() for example.
 *
 * @return N/A
 */
static void _UsageFault(const NANO_ESF *esf)
{
	PR_EXC("***** USAGE FAULT *****\n");

	_FaultThreadShow(esf);

	/* bits are sticky: they stack and must be reset */
	if (SCB->CFSR & SCB_CFSR_DIVBYZERO_Msk) {
		PR_EXC("  Division by zero\n");
	}
	if (SCB->CFSR & SCB_CFSR_UNALIGNED_Msk) {
		PR_EXC("  Unaligned memory access\n");
	}
	if (SCB->CFSR & SCB_CFSR_NOCP_Msk) {
		PR_EXC("  No coprocessor instructions\n");
	}
	if (SCB->CFSR & SCB_CFSR_INVPC_Msk) {
		PR_EXC("  Illegal load of EXC_RETURN into PC\n");
	}
	if (SCB->CFSR & SCB_CFSR_INVSTATE_Msk) {
		PR_EXC("  Illegal use of the EPSR\n");
	}
	if (SCB->CFSR & SCB_CFSR_UNDEFINSTR_Msk) {
		PR_EXC("  Attempt to execute undefined instruction\n");
	}

	/* clear USFR sticky bits */
	SCB->CFSR |= SCB_CFSR_USGFAULTSR_Msk;<commit_msg>arch: arm: Stack Overflow Usage Fault log for ARMv8-M Mainline<commit_after>/*
 * Copyright (c) 2014 Wind River Systems, Inc.
 *
 * SPDX-License-Identifier: Apache-2.0
 */

/**
 * @file
 * @brief Common fault handler for ARM Cortex-M
 *
 * Common fault handler for ARM Cortex-M processors.
 */

#include <toolchain.h>
#include <linker/sections.h>

#include <kernel.h>
#include <kernel_structs.h>
#include <inttypes.h>

#ifdef CONFIG_PRINTK
#include <misc/printk.h>
#define PR_EXC(...) printk(__VA_ARGS__)
#define STORE_xFAR(reg_var, reg) u32_t reg_var = (u32_t)reg
#else
#define PR_EXC(...)
#define STORE_xFAR(reg_var, reg)
#endif /* CONFIG_PRINTK */

#if (CONFIG_FAULT_DUMP > 0)
#define FAULT_DUMP(esf, fault) _FaultDump(esf, fault)
#else
#define FAULT_DUMP(esf, fault) \
	do {                   \
		(void) esf;    \
		(void) fault;  \
	} while ((0))
#endif

#if (CONFIG_FAULT_DUMP == 1)
/**
 *
 * @brief Dump information regarding fault (FAULT_DUMP == 1)
 *
 * Dump information regarding the fault when CONFIG_FAULT_DUMP is set to 1
 * (short form).
 *
 * eg. (precise bus error escalated to hard fault):
 *
 * Fault! EXC #3, Thread: 0x200000dc, instr: 0x000011d3
 * HARD FAULT: Escalation (see below)!
 * MMFSR: 0x00000000, BFSR: 0x00000082, UFSR: 0x00000000
 * BFAR: 0xff001234
 *
 * @return N/A
 */
void _FaultDump(const NANO_ESF *esf, int fault)
{
	PR_EXC("Fault! EXC #%d, Thread: %p, instr @ 0x%x\n",
	       fault,
	       k_current_get(),
	       esf->pc);

#if defined(CONFIG_ARMV6_M_ARMV8_M_BASELINE)
#elif defined(CONFIG_ARMV7_M_ARMV8_M_MAINLINE)
	int escalation = 0;

	if (3 == fault) { /* hard fault */
		escalation = SCB->HFSR & SCB_HFSR_FORCED_Msk;
		PR_EXC("HARD FAULT: %s\n",
		       escalation ? "Escalation (see below)!"
				  : "Bus fault on vector table read\n");
	}

	PR_EXC("MMFSR: 0x%x, BFSR: 0x%x, UFSR: 0x%x\n",
	       SCB_MMFSR, SCB_BFSR, SCB_MMFSR);

	/* In a fault handler, to determine the true faulting address:
	 * 1. Read and save the MMFAR or BFAR value.
	 * 2. Read the MMARVALID bit in the MMFSR, or the BFARVALID bit in the
	 * BFSR. The MMFAR or BFAR address is valid only if this bit is 1.
	 *
	 * Software must follow this sequence because another higher priority
	 * exception might change the MMFAR or BFAR value.
	 */
	STORE_xFAR(mmfar, SCB->MMFAR);
	STORE_xFAR(bfar, SCB->BFAR);

	if (SCB->CFSR & CFSR_MMARVALID_Msk) {
		PR_EXC("MMFAR: 0x%x\n", mmfar);
		if (escalation) {
			/* clear MMAR[VALID] to reset */
			SCB->CFSR &= ~CFSR_MMARVALID_Msk;
		}
	}
	if (SCB->CFSR & CFSR_BFARVALID_Msk) {
		PR_EXC("BFAR: 0x%x\n", bfar);
		if (escalation) {
			/* clear CFSR_BFAR[VALID] to reset */
			SCB->CFSR &= ~CFSR_BFARVALID_Msk;
		}
	}

	/* clear USFR sticky bits */
	SCB->CFSR |= SCB_CFSR_USGFAULTSR_Msk;
#else
#error Unknown ARM architecture
#endif /* CONFIG_ARMV6_M_ARMV8_M_BASELINE */
}
#endif

#if (CONFIG_FAULT_DUMP == 2)
/**
 *
 * @brief Dump thread information
 *
 * See _FaultDump() for example.
 *
 * @return N/A
 */
static void _FaultThreadShow(const NANO_ESF *esf)
{
	PR_EXC("  Executing thread ID (thread): %p\n"
	       "  Faulting instruction address:  0x%x\n",
	       k_current_get(), esf->pc);
}

#if defined(CONFIG_ARMV6_M_ARMV8_M_BASELINE)
/* HardFault is used for all fault conditions on ARMv6-M. */
#elif defined(CONFIG_ARMV7_M_ARMV8_M_MAINLINE)

/**
 *
 * @brief Dump MPU fault information
 *
 * See _FaultDump() for example.
 *
 * @return N/A
 */
static void _MpuFault(const NANO_ESF *esf, int fromHardFault)
{
	PR_EXC("***** MPU FAULT *****\n");

	_FaultThreadShow(esf);

	if (SCB->CFSR & SCB_CFSR_MSTKERR_Msk) {
		PR_EXC("  Stacking error\n");
	} else if (SCB->CFSR & SCB_CFSR_MUNSTKERR_Msk) {
		PR_EXC("  Unstacking error\n");
	} else if (SCB->CFSR & SCB_CFSR_DACCVIOL_Msk) {
		PR_EXC("  Data Access Violation\n");
		/* In a fault handler, to determine the true faulting address:
		 * 1. Read and save the MMFAR value.
		 * 2. Read the MMARVALID bit in the MMFSR.
		 * The MMFAR address is valid only if this bit is 1.
		 *
		 * Software must follow this sequence because another higher
		 * priority exception might change the MMFAR value.
		 */
		STORE_xFAR(mmfar, SCB->MMFAR);

		if (SCB->CFSR & SCB_CFSR_MMARVALID_Msk) {
			PR_EXC("  Address: 0x%x\n", mmfar);
			if (fromHardFault) {
				/* clear SCB_MMAR[VALID] to reset */
				SCB->CFSR &= ~SCB_CFSR_MMARVALID_Msk;
			}
		}
	} else if (SCB->CFSR & SCB_CFSR_IACCVIOL_Msk) {
		PR_EXC("  Instruction Access Violation\n");
#if !defined(CONFIG_ARMV7_M_ARMV8_M_FP)
	}
#else
	} else if (SCB->CFSR & SCB_CFSR_MLSPERR_Msk) {
		PR_EXC("  Floating-point lazy state preservation error\n");
	}
#endif /* !defined(CONFIG_ARMV7_M_ARMV8_M_FP) */
}

/**
 *
 * @brief Dump bus fault information
 *
 * See _FaultDump() for example.
 *
 * @return N/A
 */
static void _BusFault(const NANO_ESF *esf, int fromHardFault)
{
	PR_EXC("***** BUS FAULT *****\n");

	_FaultThreadShow(esf);

	if (SCB->CFSR & SCB_CFSR_STKERR_Msk) {
		PR_EXC("  Stacking error\n");
	} else if (SCB->CFSR & SCB_CFSR_UNSTKERR_Msk) {
		PR_EXC("  Unstacking error\n");
	} else if (SCB->CFSR & SCB_CFSR_PRECISERR_Msk) {
		PR_EXC("  Precise data bus error\n");
		/* In a fault handler, to determine the true faulting address:
		 * 1. Read and save the BFAR value.
		 * 2. Read the BFARVALID bit in the BFSR.
		 * The BFAR address is valid only if this bit is 1.
		 *
		 * Software must follow this sequence because another
		 * higher priority exception might change the BFAR value.
		 */
		STORE_xFAR(bfar, SCB->BFAR);

		if (SCB->CFSR & SCB_CFSR_BFARVALID_Msk) {
			PR_EXC("  Address: 0x%x\n", bfar);
			if (fromHardFault) {
				/* clear SCB_CFSR_BFAR[VALID] to reset */
				SCB->CFSR &= ~SCB_CFSR_BFARVALID_Msk;
			}
		}
		/* it's possible to have both a precise and imprecise fault */
		if (SCB->CFSR & SCB_CFSR_IMPRECISERR_Msk) {
			PR_EXC("  Imprecise data bus error\n");
		}
	} else if (SCB->CFSR & SCB_CFSR_IMPRECISERR_Msk) {
		PR_EXC("  Imprecise data bus error\n");
	} else if (SCB->CFSR & SCB_CFSR_IBUSERR_Msk) {
		PR_EXC("  Instruction bus error\n");
#if !defined(CONFIG_ARMV7_M_ARMV8_M_FP)
	}
#else
	} else if (SCB->CFSR & SCB_CFSR_LSPERR_Msk) {
		PR_EXC("  Floating-point lazy state preservation error\n");
	}
#endif /* !defined(CONFIG_ARMV7_M_ARMV8_M_FP) */
}

/**
 *
 * @brief Dump usage fault information
 *
 * See _FaultDump() for example.
 *
 * @return N/A
 */
static void _UsageFault(const NANO_ESF *esf)
{
	PR_EXC("***** USAGE FAULT *****\n");

	_FaultThreadShow(esf);

	/* bits are sticky: they stack and must be reset */
	if (SCB->CFSR & SCB_CFSR_DIVBYZERO_Msk) {
		PR_EXC("  Division by zero\n");
	}
	if (SCB->CFSR & SCB_CFSR_UNALIGNED_Msk) {
		PR_EXC("  Unaligned memory access\n");
	}
#if defined(CONFIG_ARMV8_M_MAINLINE)
	if (SCB->CFSR & SCB_CFSR_STKOF_Msk) {
		PR_EXC("  Stack overflow\n");
	}
#endif /* CONFIG_ARMV8_M_MAINLINE */
	if (SCB->CFSR & SCB_CFSR_NOCP_Msk) {
		PR_EXC("  No coprocessor instructions\n");
	}
	if (SCB->CFSR & SCB_CFSR_INVPC_Msk) {
		PR_EXC("  Illegal load of EXC_RETURN into PC\n");
	}
	if (SCB->CFSR & SCB_CFSR_INVSTATE_Msk) {
		PR_EXC("  Illegal use of the EPSR\n");
	}
	if (SCB->CFSR & SCB_CFSR_UNDEFINSTR_Msk) {
		PR_EXC("  Attempt to execute undefined instruction\n");
	}

	/* clear USFR sticky bits */
	SCB->CFSR |= SCB_CFSR_USGFAULTSR_Msk;
{'fraction_non_alphanumeric': 0.1350352235474646, 'fraction_numerical': 0.014856664574178698, 'mean_word_length': 3.626653759277186, 'pattern_counts': {'":': 0, '<': 15, '<?xml version=': 0, '>': 88, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 4, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7181284', 'n_tokens_mistral': 6604, 'n_tokens_neox': 6024, 'n_words': 1454}