<machine/signal.h>
[minix3.git] / lib / libvassert / vassert.c
blob31f78960988fba9e84de5312cd2da0d4d38cb9cf
1 #include <string.h>
2 #include <stdarg.h>
3 #include <signal.h>
4 #include <setjmp.h>
5 #include <minix/config.h>
6 #include <minix/const.h>
7 #include <minix/ipc.h>
8 #include <minix/com.h>
9 #include <minix/syslib.h>
10 #include <machine/stackframe.h>
11 #include "vassert.h"
13 VAssert_StateWrapper vassert_state ALIGNED(VASSERT_PAGE_SIZE);
15 #define TRUE 1
16 #define FALSE 0
18 #define MAGIC_CMD 0x564d5868
19 #define MAGIC_PORT 0x5658
20 #define HIGH_BAND_PORT 0x5659
22 #define BACKDOOR_PORT 51
23 #define BACKDOOR_HB_PORT 1
24 #define CMD_SET_ADDRESS BACKDOOR_PORT|(1<<16)
25 #define CMD_RETURN_REPLAY BACKDOOR_PORT|(2<<16)
26 #define CMD_GO_LIVE BACKDOOR_PORT|(3<<16)
27 #define CMD_LOG BACKDOOR_HB_PORT|(4<<16)
28 #define CMD_SET_RECORD 47
30 #define LOG_MAX 512
32 typedef char Bool;
33 typedef unsigned int uint32;
34 typedef unsigned long long uint64;
36 #ifdef VM_X86_64
37 typedef uint64 VA;
38 #else
39 typedef uint32 VA;
40 #endif
42 static sigjmp_buf segv_jmp;
44 void libvassert_process_backdoor(uint32, uint32, uint32, reg_t *, reg_t *,
45 reg_t *, reg_t *);
48 *---------------------------------------------------------------------
50 * sig_segv --
52 * Customed SEGV signal handler for VAssert_IsInVM.
54 * Results:
56 * None.
58 * Side effects:
59 * None.
61 *---------------------------------------------------------------------
64 static void
65 sig_segv(int sig_no)
67 /* jumping to error handling in VAssert_IsInVM. */
68 siglongjmp(segv_jmp, 1);
73 *---------------------------------------------------------------------
75 * VAssert_IsInVM --
77 * Check if we are in virtual world.
79 * Results:
81 * Return TRUE on success, or FALSE on failure.
83 * Side effects:
84 * None.
86 *---------------------------------------------------------------------
89 static Bool
90 VAssert_IsInVM(void)
92 uint32 eax, ebx, ecx, edx;
93 static Bool inVM = FALSE;
94 static Bool tested = FALSE;
95 if (!tested) {
96 /* Error handling. */
97 if (sigsetjmp(segv_jmp, 0) != 0) {
98 signal(SIGSEGV, SIG_DFL);
99 inVM = FALSE;
100 return inVM;
102 tested = TRUE;
103 /* Install custom handler. */
104 signal(SIGSEGV, sig_segv);
105 /* Test if we are in a VM. */
106 libvassert_process_backdoor(0x0a, 0, MAGIC_PORT, &eax, &ebx, &ecx, &edx);
107 signal(SIGSEGV, SIG_DFL);
108 inVM = TRUE;
110 return inVM;
115 *---------------------------------------------------------------------
117 * VAssert_Init --
119 * Tell vmx that vassert is inited.
121 * Results:
123 * Return 0 on success, or -1 on failure.
125 * Side effects:
126 * None
128 *---------------------------------------------------------------------
131 char
132 VAssert_Init(void)
134 uint32 eax, ebx, ecx, edx;
135 VA page_address = (VA) &vassert_state.inReplay;
136 if (!VAssert_IsInVM()) {
137 return -1;
139 bzero((char*) &vassert_state, sizeof vassert_state);
140 #ifndef __minix
141 /* Lock the page. */
142 if (mlock(&vassert_state, sizeof vassert_state)) {
143 return -1;
145 #endif
147 libvassert_process_backdoor(CMD_SET_ADDRESS, page_address,
148 MAGIC_PORT|(1<<16), &eax, &ebx, &ecx, &edx);
150 return (eax != -1) ? 0 : -1;
155 *---------------------------------------------------------------------
157 * VAssert_Uninit --
159 * Tell vmx that vassert is finalized.
161 * Results:
163 * Return 0 on success, or -1 on failure.
165 * Side effects:
166 * None
168 *---------------------------------------------------------------------
171 char
172 VAssert_Uninit(void)
174 unsigned int eax, ebx, ecx, edx;
175 if (!VAssert_IsInVM()) {
176 return -1;
178 libvassert_process_backdoor(CMD_SET_ADDRESS, 0, MAGIC_PORT|(0<<16), &eax, &ebx, &ecx, &edx);
179 return (eax != -1) ? 0 : 1;
184 *---------------------------------------------------------------------
186 * VAssert_LogMain --
188 * Print message to a text file on host side.
190 * Results:
191 * None
193 * Side effects:
194 * Write to a text file with fixed name.
195 * If the file exists, host UI will ask for append/replace/ignore
197 *---------------------------------------------------------------------
200 void
201 VAssert_LogMain(const char *format, ...)
203 unsigned int eax, ebx, ecx, edx;
204 char buf[LOG_MAX];
205 unsigned int len = 0;
206 va_list ap;
207 va_start(ap, format);
208 len = vsnprintf(buf, LOG_MAX, format, ap);
209 va_end(ap);
210 __asm__ __volatile__("cld; rep outsb;"
211 : "=a"(eax), "=b"(ebx), "=c"(ecx), "=d"(edx)
212 : "0"(MAGIC_CMD), "1"(CMD_LOG), "2"(len), "d"(HIGH_BAND_PORT), "S"(buf)
213 : "memory"
219 *---------------------------------------------------------------------
221 * VAssert_GoLiveMain --
223 * Make the vm which is in replay exit replay.
225 * Results:
226 * None
228 * Side effects:
229 * Replay is stopped.
231 *---------------------------------------------------------------------
234 void
235 VAssert_GoLiveMain()
237 unsigned int eax, ebx, ecx, edx;
238 vassert_state.inReplay = 0;
239 libvassert_process_backdoor(CMD_GO_LIVE, 0, MAGIC_PORT, &eax, &ebx, &ecx, &edx);
244 *---------------------------------------------------------------------
246 * VAssert_ReturnToReplayMain --
248 * Called after the custom work is done, and replay is to continue.
250 * Results:
251 * None
253 * Side effects:
254 * Replay is continued from pause.
256 *---------------------------------------------------------------------
259 void
260 VAssert_ReturnToReplayMain()
262 unsigned int eax, ebx, ecx, edx;
263 libvassert_process_backdoor(CMD_RETURN_REPLAY, 0, MAGIC_PORT, &eax, &ebx, &ecx, &edx);
268 *---------------------------------------------------------------------
270 * VAssert_SetRecordingMain --
272 * Ask vmx for starting or stopping recording.
274 * Results:
276 * Return TRUE on success, or FALSE on failure.
278 * Side effects:
279 * Recording is started or stopped.
281 *---------------------------------------------------------------------
284 char
285 VAssert_SetRecordingMain(char start)
287 uint32 eax, ebx, ecx, edx;
288 if (!VAssert_IsInVM()) {
289 return FALSE;
291 libvassert_process_backdoor(CMD_SET_RECORD, start ? 1 : 2, MAGIC_PORT, &eax, &ebx, &ecx, &edx);
292 return (eax == 1) ? TRUE : FALSE;