1 /*
2  * Copyright (c) 2020 Intel Corporation
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <zephyr/kernel.h>
8 #include <zephyr/ztest.h>
9 #include <zephyr/tc_util.h>
10 
11 #include <kernel_internal.h>
12 #if defined(__GNUC__)
13 #include "test_asm_inline_gcc.h"
14 #else
15 #include "test_asm_inline_other.h"
16 #endif
17 
18 static volatile int int_handler_executed;
19 
20 extern uint8_t z_x86_nmi_stack0[];
21 extern uint8_t z_x86_nmi_stack1[];
22 extern uint8_t z_x86_nmi_stack2[];
23 extern uint8_t z_x86_nmi_stack3[];
24 
25 uint8_t *nmi_stacks[] = {
26 	z_x86_nmi_stack0,
27 #if CONFIG_MP_MAX_NUM_CPUS > 1
28 	z_x86_nmi_stack1,
29 #if CONFIG_MP_MAX_NUM_CPUS > 2
30 	z_x86_nmi_stack2,
31 #if CONFIG_MP_MAX_NUM_CPUS > 3
32 	z_x86_nmi_stack3
33 #endif
34 #endif
35 #endif
36 };
37 
z_x86_do_kernel_nmi(const struct arch_esf * esf)38 bool z_x86_do_kernel_nmi(const struct arch_esf *esf)
39 {
40 	uint64_t stack;
41 
42 	_get_esp(stack);
43 
44 	TC_PRINT("ESP: 0x%llx CPU %d nmi_stack %p\n", stack,
45 		 arch_curr_cpu()->id, nmi_stacks[arch_curr_cpu()->id]);
46 
47 	zassert_true(stack > (uint64_t)nmi_stacks[arch_curr_cpu()->id] &&
48 		     stack < (uint64_t)nmi_stacks[arch_curr_cpu()->id] +
49 		     CONFIG_X86_EXCEPTION_STACK_SIZE, "Incorrect stack");
50 
51 	int_handler_executed++;
52 
53 	return true;
54 }
55 
ZTEST(nmi,test_nmi_handler)56 ZTEST(nmi, test_nmi_handler)
57 {
58 	TC_PRINT("Testing to see interrupt handler executes properly\n");
59 
60 	_trigger_isr_handler(IV_NON_MASKABLE_INTERRUPT);
61 
62 	zassert_not_equal(int_handler_executed, 0,
63 			  "Interrupt handler did not execute");
64 	zassert_equal(int_handler_executed, 1,
65 		      "Interrupt handler executed more than once! (%d)\n",
66 		      int_handler_executed);
67 }
68 
69 ZTEST_SUITE(nmi, NULL, NULL, NULL, NULL, NULL);
70