xtensa: check stack boundaries during backtrace

This checks for stack boundaries during backtrace to make sure
we are not stepping into invalid memory.

Signed-off-by: Daniel Leung <daniel.leung@intel.com>
diff --git a/arch/xtensa/core/xtensa_backtrace.c b/arch/xtensa/core/xtensa_backtrace.c
index e2e7e0e..70e36c9 100644
--- a/arch/xtensa/core/xtensa_backtrace.c
+++ b/arch/xtensa/core/xtensa_backtrace.c
@@ -16,6 +16,7 @@
 #endif
 
 #include <xtensa_asm2_context.h>
+#include <xtensa_stack.h>
 
 static int mask, cause;
 
@@ -39,15 +40,27 @@
 
 static inline bool xtensa_stack_ptr_is_sane(uint32_t sp)
 {
+	bool valid;
+
 #if defined(CONFIG_SOC_SERIES_ESP32)
-	return esp_stack_ptr_is_sane(sp);
+	valid = esp_stack_ptr_is_sane(sp);
 #elif defined(CONFIG_SOC_FAMILY_INTEL_ADSP)
-	return intel_adsp_ptr_is_sane(sp);
+	valid = intel_adsp_ptr_is_sane(sp);
 #elif defined(CONFIG_SOC_XTENSA_DC233C)
-	return xtensa_dc233c_stack_ptr_is_sane(sp);
+	valid = xtensa_dc233c_stack_ptr_is_sane(sp);
 #else
-#warning "xtensa_stack_ptr_is_sane is not defined for this platform"
+	/* Platform does not have additional requirements on
+	 * whether stack pointer is valid. So use the generic
+	 * test below.
+	 */
+	valid = true;
 #endif
+
+	if (valid) {
+		valid = !xtensa_is_outside_stack_bounds(sp, 0, UINT32_MAX);
+	}
+
+	return valid;
 }
 
 static inline bool xtensa_ptr_executable(const void *p)
@@ -65,6 +78,13 @@
 
 bool xtensa_backtrace_get_next_frame(struct xtensa_backtrace_frame_t *frame)
 {
+	/* Do not continue backtrace when we encounter an invalid stack
+	 * frame pointer.
+	 */
+	if (xtensa_is_outside_stack_bounds((uintptr_t)frame->sp, 0, UINT32_MAX)) {
+		return false;
+	}
+
 	/* Use frame(i-1)'s BS area located below frame(i)'s
 	 * sp to get frame(i-1)'s sp and frame(i-2)'s pc
 	 */
@@ -97,6 +117,15 @@
 	_xtensa_irq_stack_frame_raw_t *frame = (void *)interrupted_stack;
 	_xtensa_irq_bsa_t *bsa;
 
+	/* Don't dump stack if the stack pointer is invalid as
+	 * any frame elements obtained via de-referencing the
+	 * frame pointer are probably also invalid. Or worse,
+	 * cause another access violation.
+	 */
+	if (!xtensa_is_frame_pointer_valid(frame)) {
+		return -1;
+	}
+
 	bsa = frame->ptr_to_bsa;
 	cause = bsa->exccause;