summaryrefslogtreecommitdiff
path: root/test/panic.c
blob: a7333eda98ebb38e921ba798910687b2fd478264 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
/* Copyright 2021 The ChromiumOS Authors
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "assert.h"
#include "panic.h"
#include "system.h"
#include "task.h"
#include "test_util.h"

#if !(defined(CORE_CORTEX_M) || defined(CORE_CORTEX_M0))
#error "Architecture not supported"
#endif

struct reg_vals {
	int index;
	uint32_t val;
};

static const struct reg_vals EXPECTED[] = {
	{ .index = CORTEX_PANIC_REGISTER_R4, .val = 0xecec0004 },
	{ .index = CORTEX_PANIC_REGISTER_R5, .val = 0xecec0005 },
	{ .index = CORTEX_PANIC_REGISTER_R6, .val = 0xecec0006 },
	{ .index = CORTEX_PANIC_REGISTER_R7, .val = 0xecec0007 },
	{ .index = CORTEX_PANIC_REGISTER_R8, .val = 0xecec0008 },
	{ .index = CORTEX_PANIC_REGISTER_R9, .val = 0xecec0009 },
	{ .index = CORTEX_PANIC_REGISTER_R10, .val = 0xecec000a },
	{ .index = CORTEX_PANIC_REGISTER_R11, .val = 0xecec000b },
};

test_static int test_exception_panic_registers(void)
{
	if (IS_ENABLED(CORE_CORTEX_M)) {
		asm volatile("ldr r0, =0xecec0000\n"
			     "ldr r1, =0xecec0001\n"
			     "ldr r2, =0xecec0002\n"
			     "ldr r3, =0xecec0003\n"
			     "ldr r4, =0xecec0004\n"
			     "ldr r5, =0xecec0005\n"
			     "ldr r6, =0xecec0006\n"
			     "ldr r7, =0xecec0007\n"
			     "ldr r8, =0xecec0008\n"
			     "ldr r9, =0xecec0009\n"
			     "ldr r10, =0xecec000a\n"
			     "ldr r11, =0xecec000b\n"
			     "ldr r14, =0xecec000e\n"
			     /* Undefined instruction. */
			     "udf #0\n");
	} else if (IS_ENABLED(CORE_CORTEX_M0)) {
		asm volatile("ldr r1, =0xecec0001\n"
			     "ldr r2, =0xecec0002\n"
			     "ldr r3, =0xecec0003\n"
			     "ldr r4, =0xecec0004\n"
			     "ldr r5, =0xecec0005\n"
			     "ldr r6, =0xecec0006\n"
			     "ldr r7, =0xecec0007\n"
			     "ldr r0, =0xecec0008\n"
			     "mov r8, r0\n"
			     "ldr r0, =0xecec0009\n"
			     "mov r9, r0\n"
			     "ldr r0, =0xecec000a\n"
			     "mov r10, r0\n"
			     "ldr r0, =0xecec000b\n"
			     "mov r11, r0\n"
			     "ldr r0, =0xecec000e\n"
			     "mov r14, r0\n"
			     /* Undefined instruction. */
			     "udf #0\n");
	}
	__builtin_unreachable();
}

test_static void run_test_step1(void)
{
	ccprintf("Step 1: Panic\n");
	system_set_scratchpad(TEST_STATE_MASK(TEST_STATE_STEP_2));
	RUN_TEST(test_exception_panic_registers);
}

test_static int run_test_step2(void)
{
	struct panic_data *data;
	int i;

	ccprintf("Step 2: Read panic data\n");
	data = panic_get_data();
	for (i = 0; i < ARRAY_SIZE(EXPECTED); i++) {
		TEST_EQ(EXPECTED[i].val, data->cm.regs[EXPECTED[i].index],
			"%04x");
		cflush();
	}
	return EC_SUCCESS;
}

void test_run_step(uint32_t state)
{
	int ret;

	if (state & TEST_STATE_MASK(TEST_STATE_STEP_1))
		run_test_step1();
	else if (state & TEST_STATE_MASK(TEST_STATE_STEP_2)) {
		ret = run_test_step2();
		if (ret == EC_SUCCESS)
			test_reboot_to_next_step(TEST_STATE_PASSED);
		else
			test_reboot_to_next_step(TEST_STATE_FAILED);
	}
}

int task_test(void *unused)
{
	test_run_multistep();
	return EC_SUCCESS;
}

void run_test(int argc, const char **argv)
{
	msleep(30); /* Wait for TASK_ID_TEST to initialize */
	task_wake(TASK_ID_TEST);
}