1 /*
2  * Copyright (c) 2017 Oticon A/S
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 /*
8  * The basic principle of operation is:
9  *   No asynchronous behavior, no indeterminism.
10  *   If you run the same thing 20 times, you get exactly the same result 20
11  *   times.
12  *   It does not matter if you are running from console, or in a debugger
13  *   and you go for lunch in the middle of the debug session.
14  *
15  * This is achieved as follows:
16  *  The execution of native_posix is decoupled from the underlying host and its
17  *  peripherals (unless set otherwise).
18  *  In general, time in native_posix is simulated.
19  *
20  * But, native_posix can also be linked if desired to the underlying host,
21  * e.g.:You can use the provided Ethernet TAP driver, or a host BLE controller.
22  *
23  * In this case, the no-indeterminism principle is lost. Runs of native_posix
24  * will depend on the host load and the interactions with those real host
25  * peripherals.
26  *
27  */
28 
29 #include <stdio.h>
30 #include <soc.h>
31 #include "hw_models_top.h"
32 #include <stdlib.h>
33 #include <zephyr/sys/util.h>
34 #include <zephyr/sys/time_units.h>
35 #include "cmdline.h"
36 #include "irq_ctrl.h"
37 
posix_exit(int exit_code)38 void posix_exit(int exit_code)
39 {
40 	static int max_exit_code;
41 
42 	max_exit_code = MAX(exit_code, max_exit_code);
43 	/*
44 	 * posix_soc_clean_up may not return if this is called from a SW thread,
45 	 * but instead it would get posix_exit() recalled again
46 	 * ASAP from the HW thread
47 	 */
48 	posix_soc_clean_up();
49 	hwm_cleanup();
50 	native_cleanup_cmd_line();
51 	exit(max_exit_code);
52 }
53 
54 /**
55  * Run all early native_posix initialization steps, including command
56  * line parsing and CPU start, until we are ready to let the HW models
57  * run via hwm_one_event()
58  */
posix_init(int argc,char * argv[])59 void posix_init(int argc, char *argv[])
60 {
61 	/*
62 	 * Let's ensure that even if we are redirecting to a file, we get stdout
63 	 * and stderr line buffered (default for console)
64 	 * Note that glibc ignores size. But just in case we set a reasonable
65 	 * number in case somebody tries to compile against a different library
66 	 */
67 	setvbuf(stdout, NULL, _IOLBF, 512);
68 	setvbuf(stderr, NULL, _IOLBF, 512);
69 
70 	run_native_tasks(_NATIVE_PRE_BOOT_1_LEVEL);
71 
72 	native_handle_cmd_line(argc, argv);
73 
74 	run_native_tasks(_NATIVE_PRE_BOOT_2_LEVEL);
75 
76 	hwm_init();
77 
78 	run_native_tasks(_NATIVE_PRE_BOOT_3_LEVEL);
79 
80 	posix_boot_cpu();
81 
82 	run_native_tasks(_NATIVE_FIRST_SLEEP_LEVEL);
83 }
84 
85 /**
86  * Execute the simulator for at least the specified timeout, then
87  * return.  Note that this does not affect event timing, so the "next
88  * event" may be significantly after the request if the hardware has
89  * not been configured to e.g. send an interrupt when expected.
90  */
posix_exec_for(uint64_t us)91 void posix_exec_for(uint64_t us)
92 {
93 	uint64_t start = hwm_get_time();
94 
95 	do {
96 		hwm_one_event();
97 	} while (hwm_get_time() < (start + us));
98 }
99 
100 #ifndef CONFIG_ARCH_POSIX_LIBFUZZER
101 
102 /**
103  * This is the actual host process main routine.  The Zephyr
104  * application's main() is renamed via preprocessor trickery to avoid
105  * collisions.
106  *
107  * Not used when building fuzz cases, as libfuzzer has its own main()
108  * and calls the "OS" through a per-case fuzz test entry point.
109  */
main(int argc,char * argv[])110 int main(int argc, char *argv[])
111 {
112 	posix_init(argc, argv);
113 	while (true) {
114 		hwm_one_event();
115 	}
116 
117 	/* This line should be unreachable */
118 	return 1; /* LCOV_EXCL_LINE */
119 }
120 
121 #endif
122