1 /*
2  * QEMU System Emulator
3  *
4  * Copyright (c) 2003-2008 Fabrice Bellard
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a copy
7  * of this software and associated documentation files (the "Software"), to deal
8  * in the Software without restriction, including without limitation the rights
9  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10  * copies of the Software, and to permit persons to whom the Software is
11  * furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in
14  * all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22  * THE SOFTWARE.
23  */
24 
25 /* Modified for Unicorn Engine by Nguyen Anh Quynh, 2015 */
26 
27 /* Needed early for CONFIG_BSD etc. */
28 #include "config-host.h"
29 #include "sysemu/sysemu.h"
30 #include "sysemu/cpus.h"
31 #include "qemu/thread.h"
32 
33 #include "exec/address-spaces.h"	// debug, can be removed later
34 
35 #include "uc_priv.h"
36 
37 static bool cpu_can_run(CPUState *cpu);
38 static void cpu_handle_guest_debug(CPUState *cpu);
39 static int tcg_cpu_exec(struct uc_struct *uc, CPUArchState *env);
40 static bool tcg_exec_all(struct uc_struct* uc);
41 static int qemu_tcg_init_vcpu(CPUState *cpu);
42 static void qemu_tcg_cpu_loop(struct uc_struct *uc);
43 
vm_start(struct uc_struct * uc)44 int vm_start(struct uc_struct* uc)
45 {
46     if (resume_all_vcpus(uc)) {
47         return -1;
48     }
49     return 0;
50 }
51 
cpu_is_stopped(CPUState * cpu)52 bool cpu_is_stopped(CPUState *cpu)
53 {
54     return cpu->stopped;
55 }
56 
run_on_cpu(CPUState * cpu,void (* func)(void * data),void * data)57 void run_on_cpu(CPUState *cpu, void (*func)(void *data), void *data)
58 {
59     func(data);
60 }
61 
resume_all_vcpus(struct uc_struct * uc)62 int resume_all_vcpus(struct uc_struct *uc)
63 {
64     CPUState *cpu = uc->cpu;
65     // Fix call multiple time (vu).
66     // We have to check whether this is the second time, then reset all CPU.
67     if (!cpu->created) {
68         cpu->created = true;
69         cpu->halted = 0;
70         if (qemu_init_vcpu(cpu))
71             return -1;
72     }
73 
74     cpu->exit_request = 0;
75 
76     //qemu_clock_enable(QEMU_CLOCK_VIRTUAL, true);
77     cpu_resume(cpu);
78     qemu_tcg_cpu_loop(uc);
79 
80     return 0;
81 }
82 
qemu_init_vcpu(CPUState * cpu)83 int qemu_init_vcpu(CPUState *cpu)
84 {
85     cpu->nr_cores = smp_cores;
86     cpu->nr_threads = smp_threads;
87     cpu->stopped = true;
88 
89     if (tcg_enabled(cpu->uc))
90         return qemu_tcg_init_vcpu(cpu);
91 
92     return 0;
93 }
94 
qemu_tcg_cpu_loop(struct uc_struct * uc)95 static void qemu_tcg_cpu_loop(struct uc_struct *uc)
96 {
97     CPUState *cpu = uc->cpu;
98 
99     //qemu_tcg_init_cpu_signals();
100 
101     cpu->created = true;
102 
103     while (1) {
104         if (tcg_exec_all(uc))
105             break;
106     }
107 
108     cpu->created = false;
109 }
110 
qemu_tcg_init_vcpu(CPUState * cpu)111 static int qemu_tcg_init_vcpu(CPUState *cpu)
112 {
113     tcg_cpu_address_space_init(cpu, cpu->as);
114 
115     return 0;
116 }
117 
tcg_cpu_exec(struct uc_struct * uc,CPUArchState * env)118 static int tcg_cpu_exec(struct uc_struct *uc, CPUArchState *env)
119 {
120     return cpu_exec(uc, env);
121 }
122 
tcg_exec_all(struct uc_struct * uc)123 static bool tcg_exec_all(struct uc_struct* uc)
124 {
125     int r;
126     bool finish = false;
127     while (!uc->exit_request) {
128         CPUState *cpu = uc->cpu;
129         CPUArchState *env = cpu->env_ptr;
130 
131         //qemu_clock_enable(QEMU_CLOCK_VIRTUAL,
132         //                  (cpu->singlestep_enabled & SSTEP_NOTIMER) == 0);
133         if (cpu_can_run(cpu)) {
134             uc->quit_request = false;
135             r = tcg_cpu_exec(uc, env);
136 
137             // quit current TB but continue emulating?
138             if (uc->quit_request) {
139                 // reset stop_request
140                 uc->stop_request = false;
141             } else if (uc->stop_request) {
142                 //printf(">>> got STOP request!!!\n");
143                 finish = true;
144                 break;
145             }
146 
147             // save invalid memory access error & quit
148             if (env->invalid_error) {
149                 // printf(">>> invalid memory accessed, STOP = %u!!!\n", env->invalid_error);
150                 uc->invalid_addr = env->invalid_addr;
151                 uc->invalid_error = env->invalid_error;
152                 finish = true;
153                 break;
154             }
155 
156             // printf(">>> stop with r = %x, HLT=%x\n", r, EXCP_HLT);
157             if (r == EXCP_DEBUG) {
158                 cpu_handle_guest_debug(cpu);
159                 break;
160             }
161             if (r == EXCP_HLT) {
162                 //printf(">>> got HLT!!!\n");
163                 finish = true;
164                 break;
165             }
166         } else if (cpu->stop || cpu->stopped) {
167             // printf(">>> got stopped!!!\n");
168             break;
169         }
170     }
171     uc->exit_request = 0;
172 
173     return finish;
174 }
175 
cpu_can_run(CPUState * cpu)176 static bool cpu_can_run(CPUState *cpu)
177 {
178     if (cpu->stop) {
179         return false;
180     }
181     if (cpu_is_stopped(cpu)) {
182         return false;
183     }
184     return true;
185 }
186 
cpu_handle_guest_debug(CPUState * cpu)187 static void cpu_handle_guest_debug(CPUState *cpu)
188 {
189     cpu->stopped = true;
190 }
191 
192 #if 0
193 #ifndef _WIN32
194 static void qemu_tcg_init_cpu_signals(void)
195 {
196     sigset_t set;
197     struct sigaction sigact;
198 
199     memset(&sigact, 0, sizeof(sigact));
200     sigact.sa_handler = cpu_signal;
201     sigaction(SIG_IPI, &sigact, NULL);
202 
203     sigemptyset(&set);
204     sigaddset(&set, SIG_IPI);
205     pthread_sigmask(SIG_UNBLOCK, &set, NULL);
206 }
207 #else /* _WIN32 */
208 static void qemu_tcg_init_cpu_signals(void)
209 {
210 }
211 #endif /* _WIN32 */
212 #endif
213 
214