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