Statistics
| Branch: | Revision:

root / vl.c @ 7d3505c5

History | View | Annotate | Download (62.2 kB)

1 0824d6fc bellard
/*
2 80cabfad bellard
 * QEMU System Emulator
3 0824d6fc bellard
 * 
4 80cabfad bellard
 * Copyright (c) 2003-2004 Fabrice Bellard
5 0824d6fc bellard
 * 
6 1df912cf bellard
 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 1df912cf bellard
 * of this software and associated documentation files (the "Software"), to deal
8 1df912cf bellard
 * in the Software without restriction, including without limitation the rights
9 1df912cf bellard
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 1df912cf bellard
 * copies of the Software, and to permit persons to whom the Software is
11 1df912cf bellard
 * furnished to do so, subject to the following conditions:
12 1df912cf bellard
 *
13 1df912cf bellard
 * The above copyright notice and this permission notice shall be included in
14 1df912cf bellard
 * all copies or substantial portions of the Software.
15 1df912cf bellard
 *
16 1df912cf bellard
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 1df912cf bellard
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 1df912cf bellard
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 1df912cf bellard
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 1df912cf bellard
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 1df912cf bellard
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 1df912cf bellard
 * THE SOFTWARE.
23 0824d6fc bellard
 */
24 67b915a5 bellard
#include "vl.h"
25 67b915a5 bellard
26 0824d6fc bellard
#include <getopt.h>
27 0824d6fc bellard
#include <unistd.h>
28 0824d6fc bellard
#include <fcntl.h>
29 0824d6fc bellard
#include <signal.h>
30 0824d6fc bellard
#include <time.h>
31 0824d6fc bellard
#include <errno.h>
32 67b915a5 bellard
#include <sys/time.h>
33 67b915a5 bellard
34 67b915a5 bellard
#ifndef _WIN32
35 67b915a5 bellard
#include <sys/times.h>
36 f1510b2c bellard
#include <sys/wait.h>
37 67b915a5 bellard
#include <termios.h>
38 67b915a5 bellard
#include <sys/poll.h>
39 67b915a5 bellard
#include <sys/mman.h>
40 f1510b2c bellard
#include <sys/ioctl.h>
41 f1510b2c bellard
#include <sys/socket.h>
42 7d3505c5 bellard
#ifdef _BSD
43 7d3505c5 bellard
#include <sys/stat.h>
44 7d3505c5 bellard
#include <libutil.h>
45 7d3505c5 bellard
#else
46 f1510b2c bellard
#include <linux/if.h>
47 f1510b2c bellard
#include <linux/if_tun.h>
48 7d3505c5 bellard
#include <pty.h>
49 7d3505c5 bellard
#include <malloc.h>
50 fd872598 bellard
#include <linux/rtc.h>
51 67b915a5 bellard
#endif
52 7d3505c5 bellard
#endif
53 67b915a5 bellard
54 c20709aa bellard
#if defined(CONFIG_SLIRP)
55 c20709aa bellard
#include "libslirp.h"
56 c20709aa bellard
#endif
57 c20709aa bellard
58 67b915a5 bellard
#ifdef _WIN32
59 7d3505c5 bellard
#include <malloc.h>
60 67b915a5 bellard
#include <sys/timeb.h>
61 67b915a5 bellard
#include <windows.h>
62 67b915a5 bellard
#define getopt_long_only getopt_long
63 67b915a5 bellard
#define memalign(align, size) malloc(size)
64 67b915a5 bellard
#endif
65 67b915a5 bellard
66 73332e5c bellard
#ifdef CONFIG_SDL
67 7d3505c5 bellard
#if defined(__linux__)
68 73332e5c bellard
/* SDL use the pthreads and they modify sigaction. We don't
69 73332e5c bellard
   want that. */
70 7d3505c5 bellard
#if (__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 2))
71 73332e5c bellard
extern void __libc_sigaction();
72 73332e5c bellard
#define sigaction(sig, act, oact) __libc_sigaction(sig, act, oact)
73 73332e5c bellard
#else
74 73332e5c bellard
extern void __sigaction();
75 73332e5c bellard
#define sigaction(sig, act, oact) __sigaction(sig, act, oact)
76 73332e5c bellard
#endif
77 7d3505c5 bellard
#endif /* __linux__ */
78 73332e5c bellard
#endif /* CONFIG_SDL */
79 0824d6fc bellard
80 0824d6fc bellard
#include "disas.h"
81 fc01f7e7 bellard
82 8a7ddc38 bellard
#include "exec-all.h"
83 0824d6fc bellard
84 a541f297 bellard
//#define DO_TB_FLUSH
85 a541f297 bellard
86 5a67135a bellard
#define DEFAULT_NETWORK_SCRIPT "/etc/qemu-ifup"
87 f1510b2c bellard
88 0824d6fc bellard
//#define DEBUG_UNUSED_IOPORT
89 fd872598 bellard
//#define DEBUG_IOPORT
90 330d0414 bellard
91 bb551faa bellard
#if !defined(CONFIG_SOFTMMU)
92 7916e224 bellard
#define PHYS_RAM_MAX_SIZE (256 * 1024 * 1024)
93 bb551faa bellard
#else
94 bb551faa bellard
#define PHYS_RAM_MAX_SIZE (2047 * 1024 * 1024)
95 bb551faa bellard
#endif
96 7916e224 bellard
97 8a7ddc38 bellard
/* in ms */
98 8a7ddc38 bellard
#define GUI_REFRESH_INTERVAL 30
99 313aa567 bellard
100 7dea1da4 bellard
/* XXX: use a two level table to limit memory usage */
101 7dea1da4 bellard
#define MAX_IOPORTS 65536
102 0824d6fc bellard
103 80cabfad bellard
const char *bios_dir = CONFIG_QEMU_SHAREDIR;
104 0824d6fc bellard
char phys_ram_file[1024];
105 c45886db bellard
CPUState *global_env;
106 c45886db bellard
CPUState *cpu_single_env;
107 c4b1fcc0 bellard
void *ioport_opaque[MAX_IOPORTS];
108 fc01f7e7 bellard
IOPortReadFunc *ioport_read_table[3][MAX_IOPORTS];
109 fc01f7e7 bellard
IOPortWriteFunc *ioport_write_table[3][MAX_IOPORTS];
110 c45886db bellard
BlockDriverState *bs_table[MAX_DISKS], *fd_table[MAX_FD];
111 313aa567 bellard
int vga_ram_size;
112 313aa567 bellard
static DisplayState display_state;
113 a20dd508 bellard
int nographic;
114 313aa567 bellard
int64_t ticks_per_sec;
115 36b486bb bellard
int boot_device = 'c';
116 1ccde1cb bellard
static int ram_size;
117 80cabfad bellard
static char network_script[1024];
118 80cabfad bellard
int pit_min_timer_count = 0;
119 c4b1fcc0 bellard
int nb_nics;
120 c4b1fcc0 bellard
NetDriverState nd_table[MAX_NICS];
121 c4b1fcc0 bellard
SerialState *serial_console;
122 8a7ddc38 bellard
QEMUTimer *gui_timer;
123 8a7ddc38 bellard
int vm_running;
124 aaaa7df6 bellard
int audio_enabled = 0;
125 0824d6fc bellard
126 0824d6fc bellard
/***********************************************************/
127 26aa7d72 bellard
/* x86 ISA bus support */
128 26aa7d72 bellard
129 26aa7d72 bellard
target_phys_addr_t isa_mem_base = 0;
130 0824d6fc bellard
131 c4b1fcc0 bellard
uint32_t default_ioport_readb(void *opaque, uint32_t address)
132 0824d6fc bellard
{
133 0824d6fc bellard
#ifdef DEBUG_UNUSED_IOPORT
134 0824d6fc bellard
    fprintf(stderr, "inb: port=0x%04x\n", address);
135 0824d6fc bellard
#endif
136 fc01f7e7 bellard
    return 0xff;
137 0824d6fc bellard
}
138 0824d6fc bellard
139 c4b1fcc0 bellard
void default_ioport_writeb(void *opaque, uint32_t address, uint32_t data)
140 0824d6fc bellard
{
141 0824d6fc bellard
#ifdef DEBUG_UNUSED_IOPORT
142 0824d6fc bellard
    fprintf(stderr, "outb: port=0x%04x data=0x%02x\n", address, data);
143 0824d6fc bellard
#endif
144 0824d6fc bellard
}
145 0824d6fc bellard
146 0824d6fc bellard
/* default is to make two byte accesses */
147 c4b1fcc0 bellard
uint32_t default_ioport_readw(void *opaque, uint32_t address)
148 0824d6fc bellard
{
149 0824d6fc bellard
    uint32_t data;
150 c4b1fcc0 bellard
    data = ioport_read_table[0][address & (MAX_IOPORTS - 1)](opaque, address);
151 c4b1fcc0 bellard
    data |= ioport_read_table[0][(address + 1) & (MAX_IOPORTS - 1)](opaque, address + 1) << 8;
152 0824d6fc bellard
    return data;
153 0824d6fc bellard
}
154 0824d6fc bellard
155 c4b1fcc0 bellard
void default_ioport_writew(void *opaque, uint32_t address, uint32_t data)
156 0824d6fc bellard
{
157 c4b1fcc0 bellard
    ioport_write_table[0][address & (MAX_IOPORTS - 1)](opaque, address, data & 0xff);
158 c4b1fcc0 bellard
    ioport_write_table[0][(address + 1) & (MAX_IOPORTS - 1)](opaque, address + 1, (data >> 8) & 0xff);
159 0824d6fc bellard
}
160 0824d6fc bellard
161 c4b1fcc0 bellard
uint32_t default_ioport_readl(void *opaque, uint32_t address)
162 0824d6fc bellard
{
163 fc01f7e7 bellard
#ifdef DEBUG_UNUSED_IOPORT
164 fc01f7e7 bellard
    fprintf(stderr, "inl: port=0x%04x\n", address);
165 fc01f7e7 bellard
#endif
166 fc01f7e7 bellard
    return 0xffffffff;
167 0824d6fc bellard
}
168 0824d6fc bellard
169 c4b1fcc0 bellard
void default_ioport_writel(void *opaque, uint32_t address, uint32_t data)
170 0824d6fc bellard
{
171 fc01f7e7 bellard
#ifdef DEBUG_UNUSED_IOPORT
172 fc01f7e7 bellard
    fprintf(stderr, "outl: port=0x%04x data=0x%02x\n", address, data);
173 fc01f7e7 bellard
#endif
174 0824d6fc bellard
}
175 0824d6fc bellard
176 fc01f7e7 bellard
void init_ioports(void)
177 0824d6fc bellard
{
178 0824d6fc bellard
    int i;
179 0824d6fc bellard
180 fc01f7e7 bellard
    for(i = 0; i < MAX_IOPORTS; i++) {
181 fc01f7e7 bellard
        ioport_read_table[0][i] = default_ioport_readb;
182 fc01f7e7 bellard
        ioport_write_table[0][i] = default_ioport_writeb;
183 fc01f7e7 bellard
        ioport_read_table[1][i] = default_ioport_readw;
184 fc01f7e7 bellard
        ioport_write_table[1][i] = default_ioport_writew;
185 fc01f7e7 bellard
        ioport_read_table[2][i] = default_ioport_readl;
186 fc01f7e7 bellard
        ioport_write_table[2][i] = default_ioport_writel;
187 fc01f7e7 bellard
    }
188 0824d6fc bellard
}
189 0824d6fc bellard
190 fc01f7e7 bellard
/* size is the word size in byte */
191 c4b1fcc0 bellard
int register_ioport_read(int start, int length, int size, 
192 c4b1fcc0 bellard
                         IOPortReadFunc *func, void *opaque)
193 f1510b2c bellard
{
194 fc01f7e7 bellard
    int i, bsize;
195 f1510b2c bellard
196 c4b1fcc0 bellard
    if (size == 1) {
197 fc01f7e7 bellard
        bsize = 0;
198 c4b1fcc0 bellard
    } else if (size == 2) {
199 fc01f7e7 bellard
        bsize = 1;
200 c4b1fcc0 bellard
    } else if (size == 4) {
201 fc01f7e7 bellard
        bsize = 2;
202 c4b1fcc0 bellard
    } else {
203 c4b1fcc0 bellard
        hw_error("register_ioport_read: invalid size");
204 fc01f7e7 bellard
        return -1;
205 c4b1fcc0 bellard
    }
206 c4b1fcc0 bellard
    for(i = start; i < start + length; i += size) {
207 fc01f7e7 bellard
        ioport_read_table[bsize][i] = func;
208 c4b1fcc0 bellard
        if (ioport_opaque[i] != NULL && ioport_opaque[i] != opaque)
209 c4b1fcc0 bellard
            hw_error("register_ioport_read: invalid opaque");
210 c4b1fcc0 bellard
        ioport_opaque[i] = opaque;
211 c4b1fcc0 bellard
    }
212 f1510b2c bellard
    return 0;
213 f1510b2c bellard
}
214 f1510b2c bellard
215 fc01f7e7 bellard
/* size is the word size in byte */
216 c4b1fcc0 bellard
int register_ioport_write(int start, int length, int size, 
217 c4b1fcc0 bellard
                          IOPortWriteFunc *func, void *opaque)
218 f1510b2c bellard
{
219 fc01f7e7 bellard
    int i, bsize;
220 f1510b2c bellard
221 c4b1fcc0 bellard
    if (size == 1) {
222 fc01f7e7 bellard
        bsize = 0;
223 c4b1fcc0 bellard
    } else if (size == 2) {
224 fc01f7e7 bellard
        bsize = 1;
225 c4b1fcc0 bellard
    } else if (size == 4) {
226 fc01f7e7 bellard
        bsize = 2;
227 c4b1fcc0 bellard
    } else {
228 c4b1fcc0 bellard
        hw_error("register_ioport_write: invalid size");
229 fc01f7e7 bellard
        return -1;
230 c4b1fcc0 bellard
    }
231 c4b1fcc0 bellard
    for(i = start; i < start + length; i += size) {
232 fc01f7e7 bellard
        ioport_write_table[bsize][i] = func;
233 c4b1fcc0 bellard
        if (ioport_opaque[i] != NULL && ioport_opaque[i] != opaque)
234 c4b1fcc0 bellard
            hw_error("register_ioport_read: invalid opaque");
235 c4b1fcc0 bellard
        ioport_opaque[i] = opaque;
236 c4b1fcc0 bellard
    }
237 f1510b2c bellard
    return 0;
238 f1510b2c bellard
}
239 f1510b2c bellard
240 0824d6fc bellard
void pstrcpy(char *buf, int buf_size, const char *str)
241 0824d6fc bellard
{
242 0824d6fc bellard
    int c;
243 0824d6fc bellard
    char *q = buf;
244 0824d6fc bellard
245 0824d6fc bellard
    if (buf_size <= 0)
246 0824d6fc bellard
        return;
247 0824d6fc bellard
248 0824d6fc bellard
    for(;;) {
249 0824d6fc bellard
        c = *str++;
250 0824d6fc bellard
        if (c == 0 || q >= buf + buf_size - 1)
251 0824d6fc bellard
            break;
252 0824d6fc bellard
        *q++ = c;
253 0824d6fc bellard
    }
254 0824d6fc bellard
    *q = '\0';
255 0824d6fc bellard
}
256 0824d6fc bellard
257 0824d6fc bellard
/* strcat and truncate. */
258 0824d6fc bellard
char *pstrcat(char *buf, int buf_size, const char *s)
259 0824d6fc bellard
{
260 0824d6fc bellard
    int len;
261 0824d6fc bellard
    len = strlen(buf);
262 0824d6fc bellard
    if (len < buf_size) 
263 0824d6fc bellard
        pstrcpy(buf + len, buf_size - len, s);
264 0824d6fc bellard
    return buf;
265 0824d6fc bellard
}
266 0824d6fc bellard
267 0824d6fc bellard
/* return the size or -1 if error */
268 0824d6fc bellard
int load_image(const char *filename, uint8_t *addr)
269 0824d6fc bellard
{
270 0824d6fc bellard
    int fd, size;
271 40c3bac3 bellard
    fd = open(filename, O_RDONLY | O_BINARY);
272 0824d6fc bellard
    if (fd < 0)
273 0824d6fc bellard
        return -1;
274 0824d6fc bellard
    size = lseek(fd, 0, SEEK_END);
275 0824d6fc bellard
    lseek(fd, 0, SEEK_SET);
276 0824d6fc bellard
    if (read(fd, addr, size) != size) {
277 0824d6fc bellard
        close(fd);
278 0824d6fc bellard
        return -1;
279 0824d6fc bellard
    }
280 0824d6fc bellard
    close(fd);
281 0824d6fc bellard
    return size;
282 0824d6fc bellard
}
283 0824d6fc bellard
284 c45886db bellard
void cpu_outb(CPUState *env, int addr, int val)
285 0824d6fc bellard
{
286 c4b1fcc0 bellard
    addr &= (MAX_IOPORTS - 1);
287 fd872598 bellard
#ifdef DEBUG_IOPORT
288 fd872598 bellard
    if (loglevel & CPU_LOG_IOPORT)
289 fd872598 bellard
        fprintf(logfile, "outb: %04x %02x\n", addr, val);
290 fd872598 bellard
#endif    
291 c4b1fcc0 bellard
    ioport_write_table[0][addr](ioport_opaque[addr], addr, val);
292 0824d6fc bellard
}
293 0824d6fc bellard
294 c45886db bellard
void cpu_outw(CPUState *env, int addr, int val)
295 0824d6fc bellard
{
296 c4b1fcc0 bellard
    addr &= (MAX_IOPORTS - 1);
297 fd872598 bellard
#ifdef DEBUG_IOPORT
298 fd872598 bellard
    if (loglevel & CPU_LOG_IOPORT)
299 fd872598 bellard
        fprintf(logfile, "outw: %04x %04x\n", addr, val);
300 fd872598 bellard
#endif    
301 c4b1fcc0 bellard
    ioport_write_table[1][addr](ioport_opaque[addr], addr, val);
302 0824d6fc bellard
}
303 0824d6fc bellard
304 c45886db bellard
void cpu_outl(CPUState *env, int addr, int val)
305 0824d6fc bellard
{
306 c4b1fcc0 bellard
    addr &= (MAX_IOPORTS - 1);
307 fd872598 bellard
#ifdef DEBUG_IOPORT
308 fd872598 bellard
    if (loglevel & CPU_LOG_IOPORT)
309 fd872598 bellard
        fprintf(logfile, "outl: %04x %08x\n", addr, val);
310 fd872598 bellard
#endif
311 c4b1fcc0 bellard
    ioport_write_table[2][addr](ioport_opaque[addr], addr, val);
312 0824d6fc bellard
}
313 0824d6fc bellard
314 c45886db bellard
int cpu_inb(CPUState *env, int addr)
315 0824d6fc bellard
{
316 fd872598 bellard
    int val;
317 c4b1fcc0 bellard
    addr &= (MAX_IOPORTS - 1);
318 fd872598 bellard
    val = ioport_read_table[0][addr](ioport_opaque[addr], addr);
319 fd872598 bellard
#ifdef DEBUG_IOPORT
320 fd872598 bellard
    if (loglevel & CPU_LOG_IOPORT)
321 fd872598 bellard
        fprintf(logfile, "inb : %04x %02x\n", addr, val);
322 fd872598 bellard
#endif
323 fd872598 bellard
    return val;
324 0824d6fc bellard
}
325 0824d6fc bellard
326 c45886db bellard
int cpu_inw(CPUState *env, int addr)
327 0824d6fc bellard
{
328 fd872598 bellard
    int val;
329 c4b1fcc0 bellard
    addr &= (MAX_IOPORTS - 1);
330 fd872598 bellard
    val = ioport_read_table[1][addr](ioport_opaque[addr], addr);
331 fd872598 bellard
#ifdef DEBUG_IOPORT
332 fd872598 bellard
    if (loglevel & CPU_LOG_IOPORT)
333 fd872598 bellard
        fprintf(logfile, "inw : %04x %04x\n", addr, val);
334 fd872598 bellard
#endif
335 fd872598 bellard
    return val;
336 0824d6fc bellard
}
337 0824d6fc bellard
338 c45886db bellard
int cpu_inl(CPUState *env, int addr)
339 0824d6fc bellard
{
340 fd872598 bellard
    int val;
341 c4b1fcc0 bellard
    addr &= (MAX_IOPORTS - 1);
342 fd872598 bellard
    val = ioport_read_table[2][addr](ioport_opaque[addr], addr);
343 fd872598 bellard
#ifdef DEBUG_IOPORT
344 fd872598 bellard
    if (loglevel & CPU_LOG_IOPORT)
345 fd872598 bellard
        fprintf(logfile, "inl : %04x %08x\n", addr, val);
346 fd872598 bellard
#endif
347 fd872598 bellard
    return val;
348 0824d6fc bellard
}
349 0824d6fc bellard
350 0824d6fc bellard
/***********************************************************/
351 0824d6fc bellard
void hw_error(const char *fmt, ...)
352 0824d6fc bellard
{
353 0824d6fc bellard
    va_list ap;
354 0824d6fc bellard
355 0824d6fc bellard
    va_start(ap, fmt);
356 0824d6fc bellard
    fprintf(stderr, "qemu: hardware error: ");
357 0824d6fc bellard
    vfprintf(stderr, fmt, ap);
358 0824d6fc bellard
    fprintf(stderr, "\n");
359 0824d6fc bellard
#ifdef TARGET_I386
360 0824d6fc bellard
    cpu_x86_dump_state(global_env, stderr, X86_DUMP_FPU | X86_DUMP_CCOP);
361 c45886db bellard
#else
362 c45886db bellard
    cpu_dump_state(global_env, stderr, 0);
363 0824d6fc bellard
#endif
364 0824d6fc bellard
    va_end(ap);
365 0824d6fc bellard
    abort();
366 0824d6fc bellard
}
367 0824d6fc bellard
368 8a7ddc38 bellard
/***********************************************************/
369 8a7ddc38 bellard
/* timers */
370 8a7ddc38 bellard
371 34865134 bellard
#if defined(__powerpc__)
372 34865134 bellard
373 34865134 bellard
static inline uint32_t get_tbl(void) 
374 0824d6fc bellard
{
375 34865134 bellard
    uint32_t tbl;
376 34865134 bellard
    asm volatile("mftb %0" : "=r" (tbl));
377 34865134 bellard
    return tbl;
378 0824d6fc bellard
}
379 0824d6fc bellard
380 34865134 bellard
static inline uint32_t get_tbu(void) 
381 34865134 bellard
{
382 34865134 bellard
        uint32_t tbl;
383 34865134 bellard
        asm volatile("mftbu %0" : "=r" (tbl));
384 34865134 bellard
        return tbl;
385 34865134 bellard
}
386 34865134 bellard
387 34865134 bellard
int64_t cpu_get_real_ticks(void)
388 34865134 bellard
{
389 34865134 bellard
    uint32_t l, h, h1;
390 34865134 bellard
    /* NOTE: we test if wrapping has occurred */
391 34865134 bellard
    do {
392 34865134 bellard
        h = get_tbu();
393 34865134 bellard
        l = get_tbl();
394 34865134 bellard
        h1 = get_tbu();
395 34865134 bellard
    } while (h != h1);
396 34865134 bellard
    return ((int64_t)h << 32) | l;
397 34865134 bellard
}
398 34865134 bellard
399 34865134 bellard
#elif defined(__i386__)
400 34865134 bellard
401 34865134 bellard
int64_t cpu_get_real_ticks(void)
402 0824d6fc bellard
{
403 0824d6fc bellard
    int64_t val;
404 e463b581 bellard
    asm volatile ("rdtsc" : "=A" (val));
405 0824d6fc bellard
    return val;
406 0824d6fc bellard
}
407 0824d6fc bellard
408 1115dde7 bellard
#elif defined(__x86_64__)
409 1115dde7 bellard
410 1115dde7 bellard
int64_t cpu_get_real_ticks(void)
411 1115dde7 bellard
{
412 1115dde7 bellard
    uint32_t low,high;
413 1115dde7 bellard
    int64_t val;
414 1115dde7 bellard
    asm volatile("rdtsc" : "=a" (low), "=d" (high));
415 1115dde7 bellard
    val = high;
416 1115dde7 bellard
    val <<= 32;
417 1115dde7 bellard
    val |= low;
418 1115dde7 bellard
    return val;
419 1115dde7 bellard
}
420 1115dde7 bellard
421 34865134 bellard
#else
422 34865134 bellard
#error unsupported CPU
423 34865134 bellard
#endif
424 34865134 bellard
425 34865134 bellard
static int64_t cpu_ticks_offset;
426 8a7ddc38 bellard
static int cpu_ticks_enabled;
427 34865134 bellard
428 8a7ddc38 bellard
static inline int64_t cpu_get_ticks(void)
429 34865134 bellard
{
430 8a7ddc38 bellard
    if (!cpu_ticks_enabled) {
431 8a7ddc38 bellard
        return cpu_ticks_offset;
432 8a7ddc38 bellard
    } else {
433 8a7ddc38 bellard
        return cpu_get_real_ticks() + cpu_ticks_offset;
434 8a7ddc38 bellard
    }
435 34865134 bellard
}
436 34865134 bellard
437 34865134 bellard
/* enable cpu_get_ticks() */
438 34865134 bellard
void cpu_enable_ticks(void)
439 34865134 bellard
{
440 8a7ddc38 bellard
    if (!cpu_ticks_enabled) {
441 8a7ddc38 bellard
        cpu_ticks_offset -= cpu_get_real_ticks();
442 8a7ddc38 bellard
        cpu_ticks_enabled = 1;
443 8a7ddc38 bellard
    }
444 34865134 bellard
}
445 34865134 bellard
446 34865134 bellard
/* disable cpu_get_ticks() : the clock is stopped. You must not call
447 34865134 bellard
   cpu_get_ticks() after that.  */
448 34865134 bellard
void cpu_disable_ticks(void)
449 34865134 bellard
{
450 8a7ddc38 bellard
    if (cpu_ticks_enabled) {
451 8a7ddc38 bellard
        cpu_ticks_offset = cpu_get_ticks();
452 8a7ddc38 bellard
        cpu_ticks_enabled = 0;
453 8a7ddc38 bellard
    }
454 34865134 bellard
}
455 34865134 bellard
456 67b915a5 bellard
static int64_t get_clock(void)
457 34865134 bellard
{
458 67b915a5 bellard
#ifdef _WIN32
459 67b915a5 bellard
    struct _timeb tb;
460 67b915a5 bellard
    _ftime(&tb);
461 67b915a5 bellard
    return ((int64_t)tb.time * 1000 + (int64_t)tb.millitm) * 1000;
462 67b915a5 bellard
#else
463 34865134 bellard
    struct timeval tv;
464 34865134 bellard
    gettimeofday(&tv, NULL);
465 34865134 bellard
    return tv.tv_sec * 1000000LL + tv.tv_usec;
466 67b915a5 bellard
#endif
467 34865134 bellard
}
468 34865134 bellard
469 0824d6fc bellard
void cpu_calibrate_ticks(void)
470 0824d6fc bellard
{
471 0824d6fc bellard
    int64_t usec, ticks;
472 0824d6fc bellard
473 0824d6fc bellard
    usec = get_clock();
474 8a7ddc38 bellard
    ticks = cpu_get_real_ticks();
475 67b915a5 bellard
#ifdef _WIN32
476 67b915a5 bellard
    Sleep(50);
477 67b915a5 bellard
#else
478 0824d6fc bellard
    usleep(50 * 1000);
479 67b915a5 bellard
#endif
480 0824d6fc bellard
    usec = get_clock() - usec;
481 8a7ddc38 bellard
    ticks = cpu_get_real_ticks() - ticks;
482 0824d6fc bellard
    ticks_per_sec = (ticks * 1000000LL + (usec >> 1)) / usec;
483 0824d6fc bellard
}
484 0824d6fc bellard
485 87858c89 bellard
/* compute with 96 bit intermediate result: (a*b)/c */
486 80cabfad bellard
uint64_t muldiv64(uint64_t a, uint32_t b, uint32_t c)
487 87858c89 bellard
{
488 87858c89 bellard
    union {
489 87858c89 bellard
        uint64_t ll;
490 87858c89 bellard
        struct {
491 87858c89 bellard
#ifdef WORDS_BIGENDIAN
492 87858c89 bellard
            uint32_t high, low;
493 87858c89 bellard
#else
494 87858c89 bellard
            uint32_t low, high;
495 87858c89 bellard
#endif            
496 87858c89 bellard
        } l;
497 87858c89 bellard
    } u, res;
498 87858c89 bellard
    uint64_t rl, rh;
499 87858c89 bellard
500 87858c89 bellard
    u.ll = a;
501 87858c89 bellard
    rl = (uint64_t)u.l.low * (uint64_t)b;
502 87858c89 bellard
    rh = (uint64_t)u.l.high * (uint64_t)b;
503 87858c89 bellard
    rh += (rl >> 32);
504 87858c89 bellard
    res.l.high = rh / c;
505 87858c89 bellard
    res.l.low = (((rh % c) << 32) + (rl & 0xffffffff)) / c;
506 87858c89 bellard
    return res.ll;
507 87858c89 bellard
}
508 87858c89 bellard
509 8a7ddc38 bellard
#define QEMU_TIMER_REALTIME 0
510 8a7ddc38 bellard
#define QEMU_TIMER_VIRTUAL  1
511 8a7ddc38 bellard
512 8a7ddc38 bellard
struct QEMUClock {
513 8a7ddc38 bellard
    int type;
514 8a7ddc38 bellard
    /* XXX: add frequency */
515 8a7ddc38 bellard
};
516 8a7ddc38 bellard
517 8a7ddc38 bellard
struct QEMUTimer {
518 8a7ddc38 bellard
    QEMUClock *clock;
519 8a7ddc38 bellard
    int64_t expire_time;
520 8a7ddc38 bellard
    QEMUTimerCB *cb;
521 8a7ddc38 bellard
    void *opaque;
522 8a7ddc38 bellard
    struct QEMUTimer *next;
523 8a7ddc38 bellard
};
524 8a7ddc38 bellard
525 8a7ddc38 bellard
QEMUClock *rt_clock;
526 8a7ddc38 bellard
QEMUClock *vm_clock;
527 8a7ddc38 bellard
528 8a7ddc38 bellard
static QEMUTimer *active_timers[2];
529 40c3bac3 bellard
#ifdef _WIN32
530 40c3bac3 bellard
static MMRESULT timerID;
531 40c3bac3 bellard
#else
532 8a7ddc38 bellard
/* frequency of the times() clock tick */
533 8a7ddc38 bellard
static int timer_freq;
534 67b915a5 bellard
#endif
535 8a7ddc38 bellard
536 8a7ddc38 bellard
QEMUClock *qemu_new_clock(int type)
537 8a7ddc38 bellard
{
538 8a7ddc38 bellard
    QEMUClock *clock;
539 8a7ddc38 bellard
    clock = qemu_mallocz(sizeof(QEMUClock));
540 8a7ddc38 bellard
    if (!clock)
541 8a7ddc38 bellard
        return NULL;
542 8a7ddc38 bellard
    clock->type = type;
543 8a7ddc38 bellard
    return clock;
544 8a7ddc38 bellard
}
545 8a7ddc38 bellard
546 8a7ddc38 bellard
QEMUTimer *qemu_new_timer(QEMUClock *clock, QEMUTimerCB *cb, void *opaque)
547 8a7ddc38 bellard
{
548 8a7ddc38 bellard
    QEMUTimer *ts;
549 8a7ddc38 bellard
550 8a7ddc38 bellard
    ts = qemu_mallocz(sizeof(QEMUTimer));
551 8a7ddc38 bellard
    ts->clock = clock;
552 8a7ddc38 bellard
    ts->cb = cb;
553 8a7ddc38 bellard
    ts->opaque = opaque;
554 8a7ddc38 bellard
    return ts;
555 8a7ddc38 bellard
}
556 8a7ddc38 bellard
557 8a7ddc38 bellard
void qemu_free_timer(QEMUTimer *ts)
558 8a7ddc38 bellard
{
559 8a7ddc38 bellard
    qemu_free(ts);
560 8a7ddc38 bellard
}
561 8a7ddc38 bellard
562 8a7ddc38 bellard
/* stop a timer, but do not dealloc it */
563 8a7ddc38 bellard
void qemu_del_timer(QEMUTimer *ts)
564 8a7ddc38 bellard
{
565 8a7ddc38 bellard
    QEMUTimer **pt, *t;
566 8a7ddc38 bellard
567 8a7ddc38 bellard
    /* NOTE: this code must be signal safe because
568 8a7ddc38 bellard
       qemu_timer_expired() can be called from a signal. */
569 8a7ddc38 bellard
    pt = &active_timers[ts->clock->type];
570 8a7ddc38 bellard
    for(;;) {
571 8a7ddc38 bellard
        t = *pt;
572 8a7ddc38 bellard
        if (!t)
573 8a7ddc38 bellard
            break;
574 8a7ddc38 bellard
        if (t == ts) {
575 8a7ddc38 bellard
            *pt = t->next;
576 8a7ddc38 bellard
            break;
577 8a7ddc38 bellard
        }
578 8a7ddc38 bellard
        pt = &t->next;
579 8a7ddc38 bellard
    }
580 8a7ddc38 bellard
}
581 8a7ddc38 bellard
582 8a7ddc38 bellard
/* modify the current timer so that it will be fired when current_time
583 8a7ddc38 bellard
   >= expire_time. The corresponding callback will be called. */
584 8a7ddc38 bellard
void qemu_mod_timer(QEMUTimer *ts, int64_t expire_time)
585 8a7ddc38 bellard
{
586 8a7ddc38 bellard
    QEMUTimer **pt, *t;
587 8a7ddc38 bellard
588 8a7ddc38 bellard
    qemu_del_timer(ts);
589 8a7ddc38 bellard
590 8a7ddc38 bellard
    /* add the timer in the sorted list */
591 8a7ddc38 bellard
    /* NOTE: this code must be signal safe because
592 8a7ddc38 bellard
       qemu_timer_expired() can be called from a signal. */
593 8a7ddc38 bellard
    pt = &active_timers[ts->clock->type];
594 8a7ddc38 bellard
    for(;;) {
595 8a7ddc38 bellard
        t = *pt;
596 8a7ddc38 bellard
        if (!t)
597 8a7ddc38 bellard
            break;
598 8a7ddc38 bellard
        if (t->expire_time > expire_time) 
599 8a7ddc38 bellard
            break;
600 8a7ddc38 bellard
        pt = &t->next;
601 8a7ddc38 bellard
    }
602 8a7ddc38 bellard
    ts->expire_time = expire_time;
603 8a7ddc38 bellard
    ts->next = *pt;
604 8a7ddc38 bellard
    *pt = ts;
605 8a7ddc38 bellard
}
606 8a7ddc38 bellard
607 8a7ddc38 bellard
int qemu_timer_pending(QEMUTimer *ts)
608 8a7ddc38 bellard
{
609 8a7ddc38 bellard
    QEMUTimer *t;
610 8a7ddc38 bellard
    for(t = active_timers[ts->clock->type]; t != NULL; t = t->next) {
611 8a7ddc38 bellard
        if (t == ts)
612 8a7ddc38 bellard
            return 1;
613 8a7ddc38 bellard
    }
614 8a7ddc38 bellard
    return 0;
615 8a7ddc38 bellard
}
616 8a7ddc38 bellard
617 8a7ddc38 bellard
static inline int qemu_timer_expired(QEMUTimer *timer_head, int64_t current_time)
618 8a7ddc38 bellard
{
619 8a7ddc38 bellard
    if (!timer_head)
620 8a7ddc38 bellard
        return 0;
621 8a7ddc38 bellard
    return (timer_head->expire_time <= current_time);
622 8a7ddc38 bellard
}
623 8a7ddc38 bellard
624 8a7ddc38 bellard
static void qemu_run_timers(QEMUTimer **ptimer_head, int64_t current_time)
625 8a7ddc38 bellard
{
626 8a7ddc38 bellard
    QEMUTimer *ts;
627 8a7ddc38 bellard
    
628 8a7ddc38 bellard
    for(;;) {
629 8a7ddc38 bellard
        ts = *ptimer_head;
630 8a7ddc38 bellard
        if (ts->expire_time > current_time)
631 8a7ddc38 bellard
            break;
632 8a7ddc38 bellard
        /* remove timer from the list before calling the callback */
633 8a7ddc38 bellard
        *ptimer_head = ts->next;
634 8a7ddc38 bellard
        ts->next = NULL;
635 8a7ddc38 bellard
        
636 8a7ddc38 bellard
        /* run the callback (the timer list can be modified) */
637 8a7ddc38 bellard
        ts->cb(ts->opaque);
638 8a7ddc38 bellard
    }
639 8a7ddc38 bellard
}
640 8a7ddc38 bellard
641 8a7ddc38 bellard
int64_t qemu_get_clock(QEMUClock *clock)
642 8a7ddc38 bellard
{
643 8a7ddc38 bellard
    switch(clock->type) {
644 8a7ddc38 bellard
    case QEMU_TIMER_REALTIME:
645 67b915a5 bellard
#ifdef _WIN32
646 67b915a5 bellard
        return GetTickCount();
647 67b915a5 bellard
#else
648 7d3505c5 bellard
        {
649 7d3505c5 bellard
            struct tms tp;
650 7d3505c5 bellard
651 7d3505c5 bellard
            /* Note that using gettimeofday() is not a good solution
652 7d3505c5 bellard
               for timers because its value change when the date is
653 7d3505c5 bellard
               modified. */
654 7d3505c5 bellard
            if (timer_freq == 100) {
655 7d3505c5 bellard
                return times(&tp) * 10;
656 7d3505c5 bellard
            } else {
657 7d3505c5 bellard
                return ((int64_t)times(&tp) * 1000) / timer_freq;
658 7d3505c5 bellard
            }
659 8a7ddc38 bellard
        }
660 67b915a5 bellard
#endif
661 8a7ddc38 bellard
    default:
662 8a7ddc38 bellard
    case QEMU_TIMER_VIRTUAL:
663 8a7ddc38 bellard
        return cpu_get_ticks();
664 8a7ddc38 bellard
    }
665 8a7ddc38 bellard
}
666 8a7ddc38 bellard
667 8a7ddc38 bellard
/* save a timer */
668 8a7ddc38 bellard
void qemu_put_timer(QEMUFile *f, QEMUTimer *ts)
669 8a7ddc38 bellard
{
670 8a7ddc38 bellard
    uint64_t expire_time;
671 8a7ddc38 bellard
672 8a7ddc38 bellard
    if (qemu_timer_pending(ts)) {
673 8a7ddc38 bellard
        expire_time = ts->expire_time;
674 8a7ddc38 bellard
    } else {
675 8a7ddc38 bellard
        expire_time = -1;
676 8a7ddc38 bellard
    }
677 8a7ddc38 bellard
    qemu_put_be64(f, expire_time);
678 8a7ddc38 bellard
}
679 8a7ddc38 bellard
680 8a7ddc38 bellard
void qemu_get_timer(QEMUFile *f, QEMUTimer *ts)
681 8a7ddc38 bellard
{
682 8a7ddc38 bellard
    uint64_t expire_time;
683 8a7ddc38 bellard
684 8a7ddc38 bellard
    expire_time = qemu_get_be64(f);
685 8a7ddc38 bellard
    if (expire_time != -1) {
686 8a7ddc38 bellard
        qemu_mod_timer(ts, expire_time);
687 8a7ddc38 bellard
    } else {
688 8a7ddc38 bellard
        qemu_del_timer(ts);
689 8a7ddc38 bellard
    }
690 8a7ddc38 bellard
}
691 8a7ddc38 bellard
692 8a7ddc38 bellard
static void timer_save(QEMUFile *f, void *opaque)
693 8a7ddc38 bellard
{
694 8a7ddc38 bellard
    if (cpu_ticks_enabled) {
695 8a7ddc38 bellard
        hw_error("cannot save state if virtual timers are running");
696 8a7ddc38 bellard
    }
697 8a7ddc38 bellard
    qemu_put_be64s(f, &cpu_ticks_offset);
698 8a7ddc38 bellard
    qemu_put_be64s(f, &ticks_per_sec);
699 8a7ddc38 bellard
}
700 8a7ddc38 bellard
701 8a7ddc38 bellard
static int timer_load(QEMUFile *f, void *opaque, int version_id)
702 8a7ddc38 bellard
{
703 8a7ddc38 bellard
    if (version_id != 1)
704 8a7ddc38 bellard
        return -EINVAL;
705 8a7ddc38 bellard
    if (cpu_ticks_enabled) {
706 8a7ddc38 bellard
        return -EINVAL;
707 8a7ddc38 bellard
    }
708 8a7ddc38 bellard
    qemu_get_be64s(f, &cpu_ticks_offset);
709 8a7ddc38 bellard
    qemu_get_be64s(f, &ticks_per_sec);
710 8a7ddc38 bellard
    return 0;
711 8a7ddc38 bellard
}
712 8a7ddc38 bellard
713 67b915a5 bellard
#ifdef _WIN32
714 67b915a5 bellard
void CALLBACK host_alarm_handler(UINT uTimerID, UINT uMsg, 
715 67b915a5 bellard
                                 DWORD_PTR dwUser, DWORD_PTR dw1, DWORD_PTR dw2)
716 67b915a5 bellard
#else
717 8a7ddc38 bellard
static void host_alarm_handler(int host_signum)
718 67b915a5 bellard
#endif
719 8a7ddc38 bellard
{
720 8a7ddc38 bellard
    if (qemu_timer_expired(active_timers[QEMU_TIMER_VIRTUAL],
721 8a7ddc38 bellard
                           qemu_get_clock(vm_clock)) ||
722 8a7ddc38 bellard
        qemu_timer_expired(active_timers[QEMU_TIMER_REALTIME],
723 8a7ddc38 bellard
                           qemu_get_clock(rt_clock))) {
724 8a7ddc38 bellard
        /* stop the cpu because a timer occured */
725 8a7ddc38 bellard
        cpu_interrupt(global_env, CPU_INTERRUPT_EXIT);
726 8a7ddc38 bellard
    }
727 8a7ddc38 bellard
}
728 8a7ddc38 bellard
729 fd872598 bellard
#ifndef _WIN32
730 fd872598 bellard
731 fd872598 bellard
#define RTC_FREQ 1024
732 fd872598 bellard
733 fd872598 bellard
static int rtc_fd;
734 fd872598 bellard
    
735 fd872598 bellard
static int start_rtc_timer(void)
736 fd872598 bellard
{
737 fd872598 bellard
    rtc_fd = open("/dev/rtc", O_RDONLY);
738 fd872598 bellard
    if (rtc_fd < 0)
739 fd872598 bellard
        return -1;
740 fd872598 bellard
    if (ioctl(rtc_fd, RTC_IRQP_SET, RTC_FREQ) < 0) {
741 fd872598 bellard
        fprintf(stderr, "Could not configure '/dev/rtc' to have a 1024 Hz timer. This is not a fatal\n"
742 fd872598 bellard
                "error, but for better emulation accuracy either use a 2.6 host Linux kernel or\n"
743 fd872598 bellard
                "type 'echo 1024 > /proc/sys/dev/rtc/max-user-freq' as root.\n");
744 fd872598 bellard
        goto fail;
745 fd872598 bellard
    }
746 fd872598 bellard
    if (ioctl(rtc_fd, RTC_PIE_ON, 0) < 0) {
747 fd872598 bellard
    fail:
748 fd872598 bellard
        close(rtc_fd);
749 fd872598 bellard
        return -1;
750 fd872598 bellard
    }
751 fd872598 bellard
    pit_min_timer_count = PIT_FREQ / RTC_FREQ;
752 fd872598 bellard
    return 0;
753 fd872598 bellard
}
754 fd872598 bellard
755 fd872598 bellard
#endif
756 fd872598 bellard
757 8a7ddc38 bellard
static void init_timers(void)
758 8a7ddc38 bellard
{
759 8a7ddc38 bellard
    rt_clock = qemu_new_clock(QEMU_TIMER_REALTIME);
760 8a7ddc38 bellard
    vm_clock = qemu_new_clock(QEMU_TIMER_VIRTUAL);
761 8a7ddc38 bellard
762 67b915a5 bellard
#ifdef _WIN32
763 67b915a5 bellard
    {
764 67b915a5 bellard
        int count=0;
765 40c3bac3 bellard
        timerID = timeSetEvent(10,    // interval (ms)
766 40c3bac3 bellard
                               0,     // resolution
767 40c3bac3 bellard
                               host_alarm_handler, // function
768 40c3bac3 bellard
                               (DWORD)&count,  // user parameter
769 40c3bac3 bellard
                               TIME_PERIODIC | TIME_CALLBACK_FUNCTION);
770 67b915a5 bellard
         if( !timerID ) {
771 67b915a5 bellard
            perror("failed timer alarm");
772 67b915a5 bellard
            exit(1);
773 67b915a5 bellard
         }
774 67b915a5 bellard
    }
775 67b915a5 bellard
    pit_min_timer_count = ((uint64_t)10000 * PIT_FREQ) / 1000000;
776 67b915a5 bellard
#else
777 67b915a5 bellard
    {
778 67b915a5 bellard
        struct sigaction act;
779 67b915a5 bellard
        struct itimerval itv;
780 67b915a5 bellard
        
781 67b915a5 bellard
        /* get times() syscall frequency */
782 67b915a5 bellard
        timer_freq = sysconf(_SC_CLK_TCK);
783 67b915a5 bellard
        
784 67b915a5 bellard
        /* timer signal */
785 67b915a5 bellard
        sigfillset(&act.sa_mask);
786 67b915a5 bellard
        act.sa_flags = 0;
787 8a7ddc38 bellard
#if defined (TARGET_I386) && defined(USE_CODE_COPY)
788 67b915a5 bellard
        act.sa_flags |= SA_ONSTACK;
789 67b915a5 bellard
#endif
790 67b915a5 bellard
        act.sa_handler = host_alarm_handler;
791 67b915a5 bellard
        sigaction(SIGALRM, &act, NULL);
792 fd872598 bellard
793 67b915a5 bellard
        itv.it_interval.tv_sec = 0;
794 67b915a5 bellard
        itv.it_interval.tv_usec = 1000;
795 67b915a5 bellard
        itv.it_value.tv_sec = 0;
796 67b915a5 bellard
        itv.it_value.tv_usec = 10 * 1000;
797 67b915a5 bellard
        setitimer(ITIMER_REAL, &itv, NULL);
798 67b915a5 bellard
        /* we probe the tick duration of the kernel to inform the user if
799 67b915a5 bellard
           the emulated kernel requested a too high timer frequency */
800 67b915a5 bellard
        getitimer(ITIMER_REAL, &itv);
801 fd872598 bellard
802 fd872598 bellard
        if (itv.it_interval.tv_usec > 1000) {
803 fd872598 bellard
            /* try to use /dev/rtc to have a faster timer */
804 fd872598 bellard
            if (start_rtc_timer() < 0)
805 fd872598 bellard
                goto use_itimer;
806 fd872598 bellard
            /* disable itimer */
807 fd872598 bellard
            itv.it_interval.tv_sec = 0;
808 fd872598 bellard
            itv.it_interval.tv_usec = 0;
809 fd872598 bellard
            itv.it_value.tv_sec = 0;
810 fd872598 bellard
            itv.it_value.tv_usec = 0;
811 fd872598 bellard
            setitimer(ITIMER_REAL, &itv, NULL);
812 fd872598 bellard
813 fd872598 bellard
            /* use the RTC */
814 fd872598 bellard
            sigaction(SIGIO, &act, NULL);
815 fd872598 bellard
            fcntl(rtc_fd, F_SETFL, O_ASYNC);
816 fd872598 bellard
            fcntl(rtc_fd, F_SETOWN, getpid());
817 fd872598 bellard
        } else {
818 fd872598 bellard
        use_itimer:
819 fd872598 bellard
            pit_min_timer_count = ((uint64_t)itv.it_interval.tv_usec * 
820 fd872598 bellard
                                   PIT_FREQ) / 1000000;
821 fd872598 bellard
        }
822 67b915a5 bellard
    }
823 8a7ddc38 bellard
#endif
824 8a7ddc38 bellard
}
825 8a7ddc38 bellard
826 40c3bac3 bellard
void quit_timers(void)
827 40c3bac3 bellard
{
828 40c3bac3 bellard
#ifdef _WIN32
829 40c3bac3 bellard
    timeKillEvent(timerID);
830 40c3bac3 bellard
#endif
831 40c3bac3 bellard
}
832 40c3bac3 bellard
833 c4b1fcc0 bellard
/***********************************************************/
834 c4b1fcc0 bellard
/* serial device */
835 313aa567 bellard
836 67b915a5 bellard
#ifdef _WIN32
837 67b915a5 bellard
838 67b915a5 bellard
int serial_open_device(void)
839 67b915a5 bellard
{
840 67b915a5 bellard
    return -1;
841 67b915a5 bellard
}
842 67b915a5 bellard
843 67b915a5 bellard
#else
844 67b915a5 bellard
845 c4b1fcc0 bellard
int serial_open_device(void)
846 313aa567 bellard
{
847 c4b1fcc0 bellard
    char slave_name[1024];
848 c4b1fcc0 bellard
    int master_fd, slave_fd;
849 313aa567 bellard
850 c4b1fcc0 bellard
    if (serial_console == NULL && nographic) {
851 c4b1fcc0 bellard
        /* use console for serial port */
852 c4b1fcc0 bellard
        return 0;
853 80cabfad bellard
    } else {
854 c4b1fcc0 bellard
        if (openpty(&master_fd, &slave_fd, slave_name, NULL, NULL) < 0) {
855 c4b1fcc0 bellard
            fprintf(stderr, "warning: could not create pseudo terminal for serial port\n");
856 c4b1fcc0 bellard
            return -1;
857 c4b1fcc0 bellard
        }
858 c4b1fcc0 bellard
        fprintf(stderr, "Serial port redirected to %s\n", slave_name);
859 c4b1fcc0 bellard
        return master_fd;
860 330d0414 bellard
    }
861 330d0414 bellard
}
862 330d0414 bellard
863 67b915a5 bellard
#endif
864 67b915a5 bellard
865 80cabfad bellard
/***********************************************************/
866 c20709aa bellard
/* Linux network device redirectors */
867 330d0414 bellard
868 c20709aa bellard
void hex_dump(FILE *f, const uint8_t *buf, int size)
869 c20709aa bellard
{
870 c20709aa bellard
    int len, i, j, c;
871 c20709aa bellard
872 c20709aa bellard
    for(i=0;i<size;i+=16) {
873 c20709aa bellard
        len = size - i;
874 c20709aa bellard
        if (len > 16)
875 c20709aa bellard
            len = 16;
876 c20709aa bellard
        fprintf(f, "%08x ", i);
877 c20709aa bellard
        for(j=0;j<16;j++) {
878 c20709aa bellard
            if (j < len)
879 c20709aa bellard
                fprintf(f, " %02x", buf[i+j]);
880 c20709aa bellard
            else
881 c20709aa bellard
                fprintf(f, "   ");
882 c20709aa bellard
        }
883 c20709aa bellard
        fprintf(f, " ");
884 c20709aa bellard
        for(j=0;j<len;j++) {
885 c20709aa bellard
            c = buf[i+j];
886 c20709aa bellard
            if (c < ' ' || c > '~')
887 c20709aa bellard
                c = '.';
888 c20709aa bellard
            fprintf(f, "%c", c);
889 c20709aa bellard
        }
890 c20709aa bellard
        fprintf(f, "\n");
891 c20709aa bellard
    }
892 c20709aa bellard
}
893 c20709aa bellard
894 c20709aa bellard
void qemu_send_packet(NetDriverState *nd, const uint8_t *buf, int size)
895 c20709aa bellard
{
896 c20709aa bellard
    nd->send_packet(nd, buf, size);
897 c20709aa bellard
}
898 67b915a5 bellard
899 c20709aa bellard
void qemu_add_read_packet(NetDriverState *nd, IOCanRWHandler *fd_can_read, 
900 c20709aa bellard
                          IOReadHandler *fd_read, void *opaque)
901 67b915a5 bellard
{
902 c20709aa bellard
    nd->add_read_packet(nd, fd_can_read, fd_read, opaque);
903 c20709aa bellard
}
904 c20709aa bellard
905 c20709aa bellard
/* dummy network adapter */
906 c20709aa bellard
907 c20709aa bellard
static void dummy_send_packet(NetDriverState *nd, const uint8_t *buf, int size)
908 c20709aa bellard
{
909 c20709aa bellard
}
910 c20709aa bellard
911 c20709aa bellard
static void dummy_add_read_packet(NetDriverState *nd, 
912 c20709aa bellard
                                  IOCanRWHandler *fd_can_read, 
913 c20709aa bellard
                                  IOReadHandler *fd_read, void *opaque)
914 c20709aa bellard
{
915 c20709aa bellard
}
916 c20709aa bellard
917 c20709aa bellard
static int net_dummy_init(NetDriverState *nd)
918 c20709aa bellard
{
919 c20709aa bellard
    nd->send_packet = dummy_send_packet;
920 c20709aa bellard
    nd->add_read_packet = dummy_add_read_packet;
921 c20709aa bellard
    pstrcpy(nd->ifname, sizeof(nd->ifname), "dummy");
922 67b915a5 bellard
    return 0;
923 67b915a5 bellard
}
924 67b915a5 bellard
925 c20709aa bellard
#if defined(CONFIG_SLIRP)
926 c20709aa bellard
927 c20709aa bellard
/* slirp network adapter */
928 c20709aa bellard
929 c20709aa bellard
static void *slirp_fd_opaque;
930 c20709aa bellard
static IOCanRWHandler *slirp_fd_can_read;
931 c20709aa bellard
static IOReadHandler *slirp_fd_read;
932 c20709aa bellard
static int slirp_inited;
933 c20709aa bellard
934 c20709aa bellard
int slirp_can_output(void)
935 c20709aa bellard
{
936 c20709aa bellard
    return slirp_fd_can_read(slirp_fd_opaque);
937 c20709aa bellard
}
938 c20709aa bellard
939 c20709aa bellard
void slirp_output(const uint8_t *pkt, int pkt_len)
940 67b915a5 bellard
{
941 c20709aa bellard
#if 0
942 c20709aa bellard
    printf("output:\n");
943 c20709aa bellard
    hex_dump(stdout, pkt, pkt_len);
944 c20709aa bellard
#endif
945 c20709aa bellard
    slirp_fd_read(slirp_fd_opaque, pkt, pkt_len);
946 67b915a5 bellard
}
947 67b915a5 bellard
948 c20709aa bellard
static void slirp_send_packet(NetDriverState *nd, const uint8_t *buf, int size)
949 c20709aa bellard
{
950 c20709aa bellard
#if 0
951 c20709aa bellard
    printf("input:\n");
952 c20709aa bellard
    hex_dump(stdout, buf, size);
953 c20709aa bellard
#endif
954 c20709aa bellard
    slirp_input(buf, size);
955 c20709aa bellard
}
956 c20709aa bellard
957 c20709aa bellard
static void slirp_add_read_packet(NetDriverState *nd, 
958 c20709aa bellard
                                  IOCanRWHandler *fd_can_read, 
959 c20709aa bellard
                                  IOReadHandler *fd_read, void *opaque)
960 c20709aa bellard
{
961 c20709aa bellard
    slirp_fd_opaque = opaque;
962 c20709aa bellard
    slirp_fd_can_read = fd_can_read;
963 c20709aa bellard
    slirp_fd_read = fd_read;
964 c20709aa bellard
}
965 c20709aa bellard
966 c20709aa bellard
static int net_slirp_init(NetDriverState *nd)
967 c20709aa bellard
{
968 c20709aa bellard
    if (!slirp_inited) {
969 c20709aa bellard
        slirp_inited = 1;
970 c20709aa bellard
        slirp_init();
971 c20709aa bellard
    }
972 c20709aa bellard
    nd->send_packet = slirp_send_packet;
973 c20709aa bellard
    nd->add_read_packet = slirp_add_read_packet;
974 c20709aa bellard
    pstrcpy(nd->ifname, sizeof(nd->ifname), "slirp");
975 c20709aa bellard
    return 0;
976 c20709aa bellard
}
977 c20709aa bellard
978 c20709aa bellard
#endif /* CONFIG_SLIRP */
979 c20709aa bellard
980 c20709aa bellard
#if !defined(_WIN32)
981 7d3505c5 bellard
#ifdef _BSD
982 7d3505c5 bellard
static int tun_open(char *ifname, int ifname_size)
983 7d3505c5 bellard
{
984 7d3505c5 bellard
    int fd;
985 7d3505c5 bellard
    char *dev;
986 7d3505c5 bellard
    struct stat s;
987 67b915a5 bellard
988 7d3505c5 bellard
    fd = open("/dev/tap", O_RDWR);
989 7d3505c5 bellard
    if (fd < 0) {
990 7d3505c5 bellard
        fprintf(stderr, "warning: could not open /dev/tap: no virtual network emulation\n");
991 7d3505c5 bellard
        return -1;
992 7d3505c5 bellard
    }
993 7d3505c5 bellard
994 7d3505c5 bellard
    fstat(fd, &s);
995 7d3505c5 bellard
    dev = devname(s.st_rdev, S_IFCHR);
996 7d3505c5 bellard
    pstrcpy(ifname, ifname_size, dev);
997 7d3505c5 bellard
998 7d3505c5 bellard
    fcntl(fd, F_SETFL, O_NONBLOCK);
999 7d3505c5 bellard
    return fd;
1000 7d3505c5 bellard
}
1001 7d3505c5 bellard
#else
1002 c4b1fcc0 bellard
static int tun_open(char *ifname, int ifname_size)
1003 330d0414 bellard
{
1004 80cabfad bellard
    struct ifreq ifr;
1005 c4b1fcc0 bellard
    int fd, ret;
1006 80cabfad bellard
    
1007 80cabfad bellard
    fd = open("/dev/net/tun", O_RDWR);
1008 80cabfad bellard
    if (fd < 0) {
1009 80cabfad bellard
        fprintf(stderr, "warning: could not open /dev/net/tun: no virtual network emulation\n");
1010 80cabfad bellard
        return -1;
1011 330d0414 bellard
    }
1012 80cabfad bellard
    memset(&ifr, 0, sizeof(ifr));
1013 80cabfad bellard
    ifr.ifr_flags = IFF_TAP | IFF_NO_PI;
1014 80cabfad bellard
    pstrcpy(ifr.ifr_name, IFNAMSIZ, "tun%d");
1015 80cabfad bellard
    ret = ioctl(fd, TUNSETIFF, (void *) &ifr);
1016 80cabfad bellard
    if (ret != 0) {
1017 80cabfad bellard
        fprintf(stderr, "warning: could not configure /dev/net/tun: no virtual network emulation\n");
1018 80cabfad bellard
        close(fd);
1019 80cabfad bellard
        return -1;
1020 80cabfad bellard
    }
1021 80cabfad bellard
    printf("Connected to host network interface: %s\n", ifr.ifr_name);
1022 c4b1fcc0 bellard
    pstrcpy(ifname, ifname_size, ifr.ifr_name);
1023 80cabfad bellard
    fcntl(fd, F_SETFL, O_NONBLOCK);
1024 c4b1fcc0 bellard
    return fd;
1025 c4b1fcc0 bellard
}
1026 7d3505c5 bellard
#endif
1027 330d0414 bellard
1028 c20709aa bellard
static void tun_send_packet(NetDriverState *nd, const uint8_t *buf, int size)
1029 c20709aa bellard
{
1030 c20709aa bellard
    write(nd->fd, buf, size);
1031 c20709aa bellard
}
1032 c20709aa bellard
1033 c20709aa bellard
static void tun_add_read_packet(NetDriverState *nd, 
1034 c20709aa bellard
                                IOCanRWHandler *fd_can_read, 
1035 c20709aa bellard
                                IOReadHandler *fd_read, void *opaque)
1036 c4b1fcc0 bellard
{
1037 c20709aa bellard
    qemu_add_fd_read_handler(nd->fd, fd_can_read, fd_read, opaque);
1038 c20709aa bellard
}
1039 c20709aa bellard
1040 c20709aa bellard
static int net_tun_init(NetDriverState *nd)
1041 c20709aa bellard
{
1042 c20709aa bellard
    int pid, status;
1043 c20709aa bellard
    char *args[3];
1044 c4b1fcc0 bellard
    char **parg;
1045 c4b1fcc0 bellard
1046 c20709aa bellard
    nd->fd = tun_open(nd->ifname, sizeof(nd->ifname));
1047 c20709aa bellard
    if (nd->fd < 0)
1048 c20709aa bellard
        return -1;
1049 c4b1fcc0 bellard
1050 c20709aa bellard
    /* try to launch network init script */
1051 c20709aa bellard
    pid = fork();
1052 c20709aa bellard
    if (pid >= 0) {
1053 c20709aa bellard
        if (pid == 0) {
1054 c20709aa bellard
            parg = args;
1055 c20709aa bellard
            *parg++ = network_script;
1056 c20709aa bellard
            *parg++ = nd->ifname;
1057 c20709aa bellard
            *parg++ = NULL;
1058 c20709aa bellard
            execv(network_script, args);
1059 c20709aa bellard
            exit(1);
1060 c20709aa bellard
        }
1061 c20709aa bellard
        while (waitpid(pid, &status, 0) != pid);
1062 c20709aa bellard
        if (!WIFEXITED(status) ||
1063 c20709aa bellard
            WEXITSTATUS(status) != 0) {
1064 c20709aa bellard
            fprintf(stderr, "%s: could not launch network script\n",
1065 c20709aa bellard
                    network_script);
1066 80cabfad bellard
        }
1067 330d0414 bellard
    }
1068 c20709aa bellard
    nd->send_packet = tun_send_packet;
1069 c20709aa bellard
    nd->add_read_packet = tun_add_read_packet;
1070 80cabfad bellard
    return 0;
1071 330d0414 bellard
}
1072 330d0414 bellard
1073 c20709aa bellard
static int net_fd_init(NetDriverState *nd, int fd)
1074 330d0414 bellard
{
1075 c20709aa bellard
    nd->fd = fd;
1076 c20709aa bellard
    nd->send_packet = tun_send_packet;
1077 c20709aa bellard
    nd->add_read_packet = tun_add_read_packet;
1078 c20709aa bellard
    pstrcpy(nd->ifname, sizeof(nd->ifname), "tunfd");
1079 c20709aa bellard
    return 0;
1080 80cabfad bellard
}
1081 330d0414 bellard
1082 c20709aa bellard
#endif /* !_WIN32 */
1083 67b915a5 bellard
1084 330d0414 bellard
/***********************************************************/
1085 313aa567 bellard
/* dumb display */
1086 313aa567 bellard
1087 67b915a5 bellard
#ifdef _WIN32
1088 67b915a5 bellard
1089 67b915a5 bellard
static void term_exit(void)
1090 67b915a5 bellard
{
1091 67b915a5 bellard
}
1092 67b915a5 bellard
1093 67b915a5 bellard
static void term_init(void)
1094 67b915a5 bellard
{
1095 67b915a5 bellard
}
1096 67b915a5 bellard
1097 67b915a5 bellard
#else
1098 67b915a5 bellard
1099 313aa567 bellard
/* init terminal so that we can grab keys */
1100 313aa567 bellard
static struct termios oldtty;
1101 313aa567 bellard
1102 313aa567 bellard
static void term_exit(void)
1103 313aa567 bellard
{
1104 313aa567 bellard
    tcsetattr (0, TCSANOW, &oldtty);
1105 313aa567 bellard
}
1106 313aa567 bellard
1107 313aa567 bellard
static void term_init(void)
1108 313aa567 bellard
{
1109 313aa567 bellard
    struct termios tty;
1110 313aa567 bellard
1111 313aa567 bellard
    tcgetattr (0, &tty);
1112 313aa567 bellard
    oldtty = tty;
1113 313aa567 bellard
1114 313aa567 bellard
    tty.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP
1115 313aa567 bellard
                          |INLCR|IGNCR|ICRNL|IXON);
1116 313aa567 bellard
    tty.c_oflag |= OPOST;
1117 a20dd508 bellard
    tty.c_lflag &= ~(ECHO|ECHONL|ICANON|IEXTEN);
1118 a20dd508 bellard
    /* if graphical mode, we allow Ctrl-C handling */
1119 a20dd508 bellard
    if (nographic)
1120 a20dd508 bellard
        tty.c_lflag &= ~ISIG;
1121 313aa567 bellard
    tty.c_cflag &= ~(CSIZE|PARENB);
1122 313aa567 bellard
    tty.c_cflag |= CS8;
1123 313aa567 bellard
    tty.c_cc[VMIN] = 1;
1124 313aa567 bellard
    tty.c_cc[VTIME] = 0;
1125 313aa567 bellard
    
1126 313aa567 bellard
    tcsetattr (0, TCSANOW, &tty);
1127 313aa567 bellard
1128 313aa567 bellard
    atexit(term_exit);
1129 313aa567 bellard
1130 313aa567 bellard
    fcntl(0, F_SETFL, O_NONBLOCK);
1131 313aa567 bellard
}
1132 313aa567 bellard
1133 67b915a5 bellard
#endif
1134 67b915a5 bellard
1135 313aa567 bellard
static void dumb_update(DisplayState *ds, int x, int y, int w, int h)
1136 313aa567 bellard
{
1137 313aa567 bellard
}
1138 313aa567 bellard
1139 313aa567 bellard
static void dumb_resize(DisplayState *ds, int w, int h)
1140 313aa567 bellard
{
1141 313aa567 bellard
}
1142 313aa567 bellard
1143 313aa567 bellard
static void dumb_refresh(DisplayState *ds)
1144 313aa567 bellard
{
1145 313aa567 bellard
    vga_update_display();
1146 313aa567 bellard
}
1147 313aa567 bellard
1148 313aa567 bellard
void dumb_display_init(DisplayState *ds)
1149 313aa567 bellard
{
1150 313aa567 bellard
    ds->data = NULL;
1151 313aa567 bellard
    ds->linesize = 0;
1152 313aa567 bellard
    ds->depth = 0;
1153 313aa567 bellard
    ds->dpy_update = dumb_update;
1154 313aa567 bellard
    ds->dpy_resize = dumb_resize;
1155 313aa567 bellard
    ds->dpy_refresh = dumb_refresh;
1156 313aa567 bellard
}
1157 313aa567 bellard
1158 3a51dee6 bellard
#if !defined(CONFIG_SOFTMMU)
1159 313aa567 bellard
/***********************************************************/
1160 0824d6fc bellard
/* cpu signal handler */
1161 0824d6fc bellard
static void host_segv_handler(int host_signum, siginfo_t *info, 
1162 0824d6fc bellard
                              void *puc)
1163 0824d6fc bellard
{
1164 0824d6fc bellard
    if (cpu_signal_handler(host_signum, info, puc))
1165 0824d6fc bellard
        return;
1166 0824d6fc bellard
    term_exit();
1167 0824d6fc bellard
    abort();
1168 0824d6fc bellard
}
1169 3a51dee6 bellard
#endif
1170 0824d6fc bellard
1171 8a7ddc38 bellard
/***********************************************************/
1172 8a7ddc38 bellard
/* I/O handling */
1173 0824d6fc bellard
1174 c4b1fcc0 bellard
#define MAX_IO_HANDLERS 64
1175 c4b1fcc0 bellard
1176 c4b1fcc0 bellard
typedef struct IOHandlerRecord {
1177 c4b1fcc0 bellard
    int fd;
1178 c4b1fcc0 bellard
    IOCanRWHandler *fd_can_read;
1179 c4b1fcc0 bellard
    IOReadHandler *fd_read;
1180 c4b1fcc0 bellard
    void *opaque;
1181 c4b1fcc0 bellard
    /* temporary data */
1182 c4b1fcc0 bellard
    struct pollfd *ufd;
1183 c4b1fcc0 bellard
    int max_size;
1184 8a7ddc38 bellard
    struct IOHandlerRecord *next;
1185 c4b1fcc0 bellard
} IOHandlerRecord;
1186 c4b1fcc0 bellard
1187 8a7ddc38 bellard
static IOHandlerRecord *first_io_handler;
1188 c4b1fcc0 bellard
1189 8a7ddc38 bellard
int qemu_add_fd_read_handler(int fd, IOCanRWHandler *fd_can_read, 
1190 8a7ddc38 bellard
                             IOReadHandler *fd_read, void *opaque)
1191 c4b1fcc0 bellard
{
1192 c4b1fcc0 bellard
    IOHandlerRecord *ioh;
1193 c4b1fcc0 bellard
1194 8a7ddc38 bellard
    ioh = qemu_mallocz(sizeof(IOHandlerRecord));
1195 8a7ddc38 bellard
    if (!ioh)
1196 c4b1fcc0 bellard
        return -1;
1197 c4b1fcc0 bellard
    ioh->fd = fd;
1198 c4b1fcc0 bellard
    ioh->fd_can_read = fd_can_read;
1199 c4b1fcc0 bellard
    ioh->fd_read = fd_read;
1200 c4b1fcc0 bellard
    ioh->opaque = opaque;
1201 8a7ddc38 bellard
    ioh->next = first_io_handler;
1202 8a7ddc38 bellard
    first_io_handler = ioh;
1203 c4b1fcc0 bellard
    return 0;
1204 c4b1fcc0 bellard
}
1205 c4b1fcc0 bellard
1206 8a7ddc38 bellard
void qemu_del_fd_read_handler(int fd)
1207 8a7ddc38 bellard
{
1208 8a7ddc38 bellard
    IOHandlerRecord **pioh, *ioh;
1209 b4608c04 bellard
1210 8a7ddc38 bellard
    pioh = &first_io_handler;
1211 8a7ddc38 bellard
    for(;;) {
1212 8a7ddc38 bellard
        ioh = *pioh;
1213 8a7ddc38 bellard
        if (ioh == NULL)
1214 8a7ddc38 bellard
            break;
1215 8a7ddc38 bellard
        if (ioh->fd == fd) {
1216 8a7ddc38 bellard
            *pioh = ioh->next;
1217 8a7ddc38 bellard
            break;
1218 8a7ddc38 bellard
        }
1219 8a7ddc38 bellard
        pioh = &ioh->next;
1220 8a7ddc38 bellard
    }
1221 8a7ddc38 bellard
}
1222 8a7ddc38 bellard
1223 8a7ddc38 bellard
/***********************************************************/
1224 8a7ddc38 bellard
/* savevm/loadvm support */
1225 8a7ddc38 bellard
1226 8a7ddc38 bellard
void qemu_put_buffer(QEMUFile *f, const uint8_t *buf, int size)
1227 b4608c04 bellard
{
1228 8a7ddc38 bellard
    fwrite(buf, 1, size, f);
1229 b4608c04 bellard
}
1230 b4608c04 bellard
1231 8a7ddc38 bellard
void qemu_put_byte(QEMUFile *f, int v)
1232 b4608c04 bellard
{
1233 8a7ddc38 bellard
    fputc(v, f);
1234 8a7ddc38 bellard
}
1235 8a7ddc38 bellard
1236 8a7ddc38 bellard
void qemu_put_be16(QEMUFile *f, unsigned int v)
1237 8a7ddc38 bellard
{
1238 8a7ddc38 bellard
    qemu_put_byte(f, v >> 8);
1239 8a7ddc38 bellard
    qemu_put_byte(f, v);
1240 8a7ddc38 bellard
}
1241 8a7ddc38 bellard
1242 8a7ddc38 bellard
void qemu_put_be32(QEMUFile *f, unsigned int v)
1243 8a7ddc38 bellard
{
1244 8a7ddc38 bellard
    qemu_put_byte(f, v >> 24);
1245 8a7ddc38 bellard
    qemu_put_byte(f, v >> 16);
1246 8a7ddc38 bellard
    qemu_put_byte(f, v >> 8);
1247 8a7ddc38 bellard
    qemu_put_byte(f, v);
1248 8a7ddc38 bellard
}
1249 8a7ddc38 bellard
1250 8a7ddc38 bellard
void qemu_put_be64(QEMUFile *f, uint64_t v)
1251 8a7ddc38 bellard
{
1252 8a7ddc38 bellard
    qemu_put_be32(f, v >> 32);
1253 8a7ddc38 bellard
    qemu_put_be32(f, v);
1254 8a7ddc38 bellard
}
1255 8a7ddc38 bellard
1256 8a7ddc38 bellard
int qemu_get_buffer(QEMUFile *f, uint8_t *buf, int size)
1257 8a7ddc38 bellard
{
1258 8a7ddc38 bellard
    return fread(buf, 1, size, f);
1259 8a7ddc38 bellard
}
1260 8a7ddc38 bellard
1261 8a7ddc38 bellard
int qemu_get_byte(QEMUFile *f)
1262 8a7ddc38 bellard
{
1263 8a7ddc38 bellard
    int v;
1264 8a7ddc38 bellard
    v = fgetc(f);
1265 8a7ddc38 bellard
    if (v == EOF)
1266 8a7ddc38 bellard
        return 0;
1267 8a7ddc38 bellard
    else
1268 8a7ddc38 bellard
        return v;
1269 8a7ddc38 bellard
}
1270 8a7ddc38 bellard
1271 8a7ddc38 bellard
unsigned int qemu_get_be16(QEMUFile *f)
1272 8a7ddc38 bellard
{
1273 8a7ddc38 bellard
    unsigned int v;
1274 8a7ddc38 bellard
    v = qemu_get_byte(f) << 8;
1275 8a7ddc38 bellard
    v |= qemu_get_byte(f);
1276 8a7ddc38 bellard
    return v;
1277 8a7ddc38 bellard
}
1278 8a7ddc38 bellard
1279 8a7ddc38 bellard
unsigned int qemu_get_be32(QEMUFile *f)
1280 8a7ddc38 bellard
{
1281 8a7ddc38 bellard
    unsigned int v;
1282 8a7ddc38 bellard
    v = qemu_get_byte(f) << 24;
1283 8a7ddc38 bellard
    v |= qemu_get_byte(f) << 16;
1284 8a7ddc38 bellard
    v |= qemu_get_byte(f) << 8;
1285 8a7ddc38 bellard
    v |= qemu_get_byte(f);
1286 8a7ddc38 bellard
    return v;
1287 8a7ddc38 bellard
}
1288 8a7ddc38 bellard
1289 8a7ddc38 bellard
uint64_t qemu_get_be64(QEMUFile *f)
1290 8a7ddc38 bellard
{
1291 8a7ddc38 bellard
    uint64_t v;
1292 8a7ddc38 bellard
    v = (uint64_t)qemu_get_be32(f) << 32;
1293 8a7ddc38 bellard
    v |= qemu_get_be32(f);
1294 8a7ddc38 bellard
    return v;
1295 8a7ddc38 bellard
}
1296 8a7ddc38 bellard
1297 8a7ddc38 bellard
int64_t qemu_ftell(QEMUFile *f)
1298 8a7ddc38 bellard
{
1299 8a7ddc38 bellard
    return ftell(f);
1300 8a7ddc38 bellard
}
1301 8a7ddc38 bellard
1302 8a7ddc38 bellard
int64_t qemu_fseek(QEMUFile *f, int64_t pos, int whence)
1303 8a7ddc38 bellard
{
1304 8a7ddc38 bellard
    if (fseek(f, pos, whence) < 0)
1305 8a7ddc38 bellard
        return -1;
1306 8a7ddc38 bellard
    return ftell(f);
1307 8a7ddc38 bellard
}
1308 8a7ddc38 bellard
1309 8a7ddc38 bellard
typedef struct SaveStateEntry {
1310 8a7ddc38 bellard
    char idstr[256];
1311 8a7ddc38 bellard
    int instance_id;
1312 8a7ddc38 bellard
    int version_id;
1313 8a7ddc38 bellard
    SaveStateHandler *save_state;
1314 8a7ddc38 bellard
    LoadStateHandler *load_state;
1315 8a7ddc38 bellard
    void *opaque;
1316 8a7ddc38 bellard
    struct SaveStateEntry *next;
1317 8a7ddc38 bellard
} SaveStateEntry;
1318 b4608c04 bellard
1319 8a7ddc38 bellard
static SaveStateEntry *first_se;
1320 8a7ddc38 bellard
1321 8a7ddc38 bellard
int register_savevm(const char *idstr, 
1322 8a7ddc38 bellard
                    int instance_id, 
1323 8a7ddc38 bellard
                    int version_id,
1324 8a7ddc38 bellard
                    SaveStateHandler *save_state,
1325 8a7ddc38 bellard
                    LoadStateHandler *load_state,
1326 8a7ddc38 bellard
                    void *opaque)
1327 8a7ddc38 bellard
{
1328 8a7ddc38 bellard
    SaveStateEntry *se, **pse;
1329 8a7ddc38 bellard
1330 8a7ddc38 bellard
    se = qemu_malloc(sizeof(SaveStateEntry));
1331 8a7ddc38 bellard
    if (!se)
1332 8a7ddc38 bellard
        return -1;
1333 8a7ddc38 bellard
    pstrcpy(se->idstr, sizeof(se->idstr), idstr);
1334 8a7ddc38 bellard
    se->instance_id = instance_id;
1335 8a7ddc38 bellard
    se->version_id = version_id;
1336 8a7ddc38 bellard
    se->save_state = save_state;
1337 8a7ddc38 bellard
    se->load_state = load_state;
1338 8a7ddc38 bellard
    se->opaque = opaque;
1339 8a7ddc38 bellard
    se->next = NULL;
1340 8a7ddc38 bellard
1341 8a7ddc38 bellard
    /* add at the end of list */
1342 8a7ddc38 bellard
    pse = &first_se;
1343 8a7ddc38 bellard
    while (*pse != NULL)
1344 8a7ddc38 bellard
        pse = &(*pse)->next;
1345 8a7ddc38 bellard
    *pse = se;
1346 8a7ddc38 bellard
    return 0;
1347 8a7ddc38 bellard
}
1348 8a7ddc38 bellard
1349 8a7ddc38 bellard
#define QEMU_VM_FILE_MAGIC   0x5145564d
1350 8a7ddc38 bellard
#define QEMU_VM_FILE_VERSION 0x00000001
1351 8a7ddc38 bellard
1352 8a7ddc38 bellard
int qemu_savevm(const char *filename)
1353 8a7ddc38 bellard
{
1354 8a7ddc38 bellard
    SaveStateEntry *se;
1355 8a7ddc38 bellard
    QEMUFile *f;
1356 8a7ddc38 bellard
    int len, len_pos, cur_pos, saved_vm_running, ret;
1357 8a7ddc38 bellard
1358 8a7ddc38 bellard
    saved_vm_running = vm_running;
1359 8a7ddc38 bellard
    vm_stop(0);
1360 8a7ddc38 bellard
1361 8a7ddc38 bellard
    f = fopen(filename, "wb");
1362 8a7ddc38 bellard
    if (!f) {
1363 8a7ddc38 bellard
        ret = -1;
1364 8a7ddc38 bellard
        goto the_end;
1365 313aa567 bellard
    }
1366 313aa567 bellard
1367 8a7ddc38 bellard
    qemu_put_be32(f, QEMU_VM_FILE_MAGIC);
1368 8a7ddc38 bellard
    qemu_put_be32(f, QEMU_VM_FILE_VERSION);
1369 8a7ddc38 bellard
1370 8a7ddc38 bellard
    for(se = first_se; se != NULL; se = se->next) {
1371 8a7ddc38 bellard
        /* ID string */
1372 8a7ddc38 bellard
        len = strlen(se->idstr);
1373 8a7ddc38 bellard
        qemu_put_byte(f, len);
1374 8a7ddc38 bellard
        qemu_put_buffer(f, se->idstr, len);
1375 8a7ddc38 bellard
1376 8a7ddc38 bellard
        qemu_put_be32(f, se->instance_id);
1377 8a7ddc38 bellard
        qemu_put_be32(f, se->version_id);
1378 8a7ddc38 bellard
1379 8a7ddc38 bellard
        /* record size: filled later */
1380 8a7ddc38 bellard
        len_pos = ftell(f);
1381 8a7ddc38 bellard
        qemu_put_be32(f, 0);
1382 8a7ddc38 bellard
        
1383 8a7ddc38 bellard
        se->save_state(f, se->opaque);
1384 8a7ddc38 bellard
1385 8a7ddc38 bellard
        /* fill record size */
1386 8a7ddc38 bellard
        cur_pos = ftell(f);
1387 8a7ddc38 bellard
        len = ftell(f) - len_pos - 4;
1388 8a7ddc38 bellard
        fseek(f, len_pos, SEEK_SET);
1389 8a7ddc38 bellard
        qemu_put_be32(f, len);
1390 8a7ddc38 bellard
        fseek(f, cur_pos, SEEK_SET);
1391 8a7ddc38 bellard
    }
1392 8a7ddc38 bellard
1393 8a7ddc38 bellard
    fclose(f);
1394 8a7ddc38 bellard
    ret = 0;
1395 8a7ddc38 bellard
 the_end:
1396 8a7ddc38 bellard
    if (saved_vm_running)
1397 8a7ddc38 bellard
        vm_start();
1398 8a7ddc38 bellard
    return ret;
1399 8a7ddc38 bellard
}
1400 8a7ddc38 bellard
1401 8a7ddc38 bellard
static SaveStateEntry *find_se(const char *idstr, int instance_id)
1402 8a7ddc38 bellard
{
1403 8a7ddc38 bellard
    SaveStateEntry *se;
1404 8a7ddc38 bellard
1405 8a7ddc38 bellard
    for(se = first_se; se != NULL; se = se->next) {
1406 8a7ddc38 bellard
        if (!strcmp(se->idstr, idstr) && 
1407 8a7ddc38 bellard
            instance_id == se->instance_id)
1408 8a7ddc38 bellard
            return se;
1409 8a7ddc38 bellard
    }
1410 8a7ddc38 bellard
    return NULL;
1411 8a7ddc38 bellard
}
1412 8a7ddc38 bellard
1413 8a7ddc38 bellard
int qemu_loadvm(const char *filename)
1414 8a7ddc38 bellard
{
1415 8a7ddc38 bellard
    SaveStateEntry *se;
1416 8a7ddc38 bellard
    QEMUFile *f;
1417 8a7ddc38 bellard
    int len, cur_pos, ret, instance_id, record_len, version_id;
1418 8a7ddc38 bellard
    int saved_vm_running;
1419 8a7ddc38 bellard
    unsigned int v;
1420 8a7ddc38 bellard
    char idstr[256];
1421 8a7ddc38 bellard
    
1422 8a7ddc38 bellard
    saved_vm_running = vm_running;
1423 8a7ddc38 bellard
    vm_stop(0);
1424 8a7ddc38 bellard
1425 8a7ddc38 bellard
    f = fopen(filename, "rb");
1426 8a7ddc38 bellard
    if (!f) {
1427 8a7ddc38 bellard
        ret = -1;
1428 8a7ddc38 bellard
        goto the_end;
1429 8a7ddc38 bellard
    }
1430 8a7ddc38 bellard
1431 8a7ddc38 bellard
    v = qemu_get_be32(f);
1432 8a7ddc38 bellard
    if (v != QEMU_VM_FILE_MAGIC)
1433 8a7ddc38 bellard
        goto fail;
1434 8a7ddc38 bellard
    v = qemu_get_be32(f);
1435 8a7ddc38 bellard
    if (v != QEMU_VM_FILE_VERSION) {
1436 8a7ddc38 bellard
    fail:
1437 8a7ddc38 bellard
        fclose(f);
1438 8a7ddc38 bellard
        ret = -1;
1439 8a7ddc38 bellard
        goto the_end;
1440 8a7ddc38 bellard
    }
1441 b4608c04 bellard
    for(;;) {
1442 a541f297 bellard
#if defined (DO_TB_FLUSH)
1443 d927637d bellard
        tb_flush(global_env);
1444 a541f297 bellard
#endif
1445 8a7ddc38 bellard
        len = qemu_get_byte(f);
1446 8a7ddc38 bellard
        if (feof(f))
1447 cd4c3e88 bellard
            break;
1448 8a7ddc38 bellard
        qemu_get_buffer(f, idstr, len);
1449 8a7ddc38 bellard
        idstr[len] = '\0';
1450 8a7ddc38 bellard
        instance_id = qemu_get_be32(f);
1451 8a7ddc38 bellard
        version_id = qemu_get_be32(f);
1452 8a7ddc38 bellard
        record_len = qemu_get_be32(f);
1453 8a7ddc38 bellard
#if 0
1454 8a7ddc38 bellard
        printf("idstr=%s instance=0x%x version=%d len=%d\n", 
1455 8a7ddc38 bellard
               idstr, instance_id, version_id, record_len);
1456 8a7ddc38 bellard
#endif
1457 8a7ddc38 bellard
        cur_pos = ftell(f);
1458 8a7ddc38 bellard
        se = find_se(idstr, instance_id);
1459 8a7ddc38 bellard
        if (!se) {
1460 8a7ddc38 bellard
            fprintf(stderr, "qemu: warning: instance 0x%x of device '%s' not present in current VM\n", 
1461 8a7ddc38 bellard
                    instance_id, idstr);
1462 8a7ddc38 bellard
        } else {
1463 8a7ddc38 bellard
            ret = se->load_state(f, se->opaque, version_id);
1464 8a7ddc38 bellard
            if (ret < 0) {
1465 8a7ddc38 bellard
                fprintf(stderr, "qemu: warning: error while loading state for instance 0x%x of device '%s'\n", 
1466 8a7ddc38 bellard
                        instance_id, idstr);
1467 8a7ddc38 bellard
            }
1468 34865134 bellard
        }
1469 8a7ddc38 bellard
        /* always seek to exact end of record */
1470 8a7ddc38 bellard
        qemu_fseek(f, cur_pos + record_len, SEEK_SET);
1471 8a7ddc38 bellard
    }
1472 8a7ddc38 bellard
    fclose(f);
1473 8a7ddc38 bellard
    ret = 0;
1474 8a7ddc38 bellard
 the_end:
1475 8a7ddc38 bellard
    if (saved_vm_running)
1476 8a7ddc38 bellard
        vm_start();
1477 8a7ddc38 bellard
    return ret;
1478 8a7ddc38 bellard
}
1479 8a7ddc38 bellard
1480 8a7ddc38 bellard
/***********************************************************/
1481 8a7ddc38 bellard
/* cpu save/restore */
1482 8a7ddc38 bellard
1483 8a7ddc38 bellard
#if defined(TARGET_I386)
1484 8a7ddc38 bellard
1485 8a7ddc38 bellard
static void cpu_put_seg(QEMUFile *f, SegmentCache *dt)
1486 8a7ddc38 bellard
{
1487 8a7ddc38 bellard
    qemu_put_be32(f, (uint32_t)dt->base);
1488 8a7ddc38 bellard
    qemu_put_be32(f, dt->limit);
1489 8a7ddc38 bellard
    qemu_put_be32(f, dt->flags);
1490 8a7ddc38 bellard
}
1491 8a7ddc38 bellard
1492 8a7ddc38 bellard
static void cpu_get_seg(QEMUFile *f, SegmentCache *dt)
1493 8a7ddc38 bellard
{
1494 8a7ddc38 bellard
    dt->base = (uint8_t *)qemu_get_be32(f);
1495 8a7ddc38 bellard
    dt->limit = qemu_get_be32(f);
1496 8a7ddc38 bellard
    dt->flags = qemu_get_be32(f);
1497 8a7ddc38 bellard
}
1498 8a7ddc38 bellard
1499 8a7ddc38 bellard
void cpu_save(QEMUFile *f, void *opaque)
1500 8a7ddc38 bellard
{
1501 8a7ddc38 bellard
    CPUState *env = opaque;
1502 8a7ddc38 bellard
    uint16_t fptag, fpus, fpuc;
1503 8a7ddc38 bellard
    uint32_t hflags;
1504 8a7ddc38 bellard
    int i;
1505 8a7ddc38 bellard
1506 8a7ddc38 bellard
    for(i = 0; i < 8; i++)
1507 8a7ddc38 bellard
        qemu_put_be32s(f, &env->regs[i]);
1508 8a7ddc38 bellard
    qemu_put_be32s(f, &env->eip);
1509 8a7ddc38 bellard
    qemu_put_be32s(f, &env->eflags);
1510 8a7ddc38 bellard
    qemu_put_be32s(f, &env->eflags);
1511 8a7ddc38 bellard
    hflags = env->hflags; /* XXX: suppress most of the redundant hflags */
1512 8a7ddc38 bellard
    qemu_put_be32s(f, &hflags);
1513 8a7ddc38 bellard
    
1514 8a7ddc38 bellard
    /* FPU */
1515 8a7ddc38 bellard
    fpuc = env->fpuc;
1516 8a7ddc38 bellard
    fpus = (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11;
1517 8a7ddc38 bellard
    fptag = 0;
1518 8a7ddc38 bellard
    for (i=7; i>=0; i--) {
1519 8a7ddc38 bellard
        fptag <<= 2;
1520 8a7ddc38 bellard
        if (env->fptags[i]) {
1521 8a7ddc38 bellard
            fptag |= 3;
1522 8a7ddc38 bellard
        }
1523 8a7ddc38 bellard
    }
1524 8a7ddc38 bellard
    
1525 8a7ddc38 bellard
    qemu_put_be16s(f, &fpuc);
1526 8a7ddc38 bellard
    qemu_put_be16s(f, &fpus);
1527 8a7ddc38 bellard
    qemu_put_be16s(f, &fptag);
1528 8a7ddc38 bellard
1529 8a7ddc38 bellard
    for(i = 0; i < 8; i++) {
1530 8a7ddc38 bellard
        uint64_t mant;
1531 8a7ddc38 bellard
        uint16_t exp;
1532 8a7ddc38 bellard
        cpu_get_fp80(&mant, &exp, env->fpregs[i]);
1533 8a7ddc38 bellard
        qemu_put_be64(f, mant);
1534 8a7ddc38 bellard
        qemu_put_be16(f, exp);
1535 8a7ddc38 bellard
    }
1536 8a7ddc38 bellard
1537 8a7ddc38 bellard
    for(i = 0; i < 6; i++)
1538 8a7ddc38 bellard
        cpu_put_seg(f, &env->segs[i]);
1539 8a7ddc38 bellard
    cpu_put_seg(f, &env->ldt);
1540 8a7ddc38 bellard
    cpu_put_seg(f, &env->tr);
1541 8a7ddc38 bellard
    cpu_put_seg(f, &env->gdt);
1542 8a7ddc38 bellard
    cpu_put_seg(f, &env->idt);
1543 8a7ddc38 bellard
    
1544 8a7ddc38 bellard
    qemu_put_be32s(f, &env->sysenter_cs);
1545 8a7ddc38 bellard
    qemu_put_be32s(f, &env->sysenter_esp);
1546 8a7ddc38 bellard
    qemu_put_be32s(f, &env->sysenter_eip);
1547 8a7ddc38 bellard
    
1548 8a7ddc38 bellard
    qemu_put_be32s(f, &env->cr[0]);
1549 8a7ddc38 bellard
    qemu_put_be32s(f, &env->cr[2]);
1550 8a7ddc38 bellard
    qemu_put_be32s(f, &env->cr[3]);
1551 8a7ddc38 bellard
    qemu_put_be32s(f, &env->cr[4]);
1552 8a7ddc38 bellard
    
1553 8a7ddc38 bellard
    for(i = 0; i < 8; i++)
1554 8a7ddc38 bellard
        qemu_put_be32s(f, &env->dr[i]);
1555 8a7ddc38 bellard
1556 8a7ddc38 bellard
    /* MMU */
1557 8a7ddc38 bellard
    qemu_put_be32s(f, &env->a20_mask);
1558 8a7ddc38 bellard
}
1559 8a7ddc38 bellard
1560 8a7ddc38 bellard
int cpu_load(QEMUFile *f, void *opaque, int version_id)
1561 8a7ddc38 bellard
{
1562 8a7ddc38 bellard
    CPUState *env = opaque;
1563 8a7ddc38 bellard
    int i;
1564 8a7ddc38 bellard
    uint32_t hflags;
1565 8a7ddc38 bellard
    uint16_t fpus, fpuc, fptag;
1566 8a7ddc38 bellard
1567 8a7ddc38 bellard
    if (version_id != 1)
1568 8a7ddc38 bellard
        return -EINVAL;
1569 8a7ddc38 bellard
    for(i = 0; i < 8; i++)
1570 8a7ddc38 bellard
        qemu_get_be32s(f, &env->regs[i]);
1571 8a7ddc38 bellard
    qemu_get_be32s(f, &env->eip);
1572 8a7ddc38 bellard
    qemu_get_be32s(f, &env->eflags);
1573 8a7ddc38 bellard
    qemu_get_be32s(f, &env->eflags);
1574 8a7ddc38 bellard
    qemu_get_be32s(f, &hflags);
1575 8a7ddc38 bellard
1576 8a7ddc38 bellard
    qemu_get_be16s(f, &fpuc);
1577 8a7ddc38 bellard
    qemu_get_be16s(f, &fpus);
1578 8a7ddc38 bellard
    qemu_get_be16s(f, &fptag);
1579 8a7ddc38 bellard
1580 8a7ddc38 bellard
    for(i = 0; i < 8; i++) {
1581 8a7ddc38 bellard
        uint64_t mant;
1582 8a7ddc38 bellard
        uint16_t exp;
1583 8a7ddc38 bellard
        mant = qemu_get_be64(f);
1584 8a7ddc38 bellard
        exp = qemu_get_be16(f);
1585 8a7ddc38 bellard
        env->fpregs[i] = cpu_set_fp80(mant, exp);
1586 8a7ddc38 bellard
    }
1587 8a7ddc38 bellard
1588 8a7ddc38 bellard
    env->fpuc = fpuc;
1589 8a7ddc38 bellard
    env->fpstt = (fpus >> 11) & 7;
1590 8a7ddc38 bellard
    env->fpus = fpus & ~0x3800;
1591 8a7ddc38 bellard
    for(i = 0; i < 8; i++) {
1592 8a7ddc38 bellard
        env->fptags[i] = ((fptag & 3) == 3);
1593 8a7ddc38 bellard
        fptag >>= 2;
1594 8a7ddc38 bellard
    }
1595 8a7ddc38 bellard
    
1596 8a7ddc38 bellard
    for(i = 0; i < 6; i++)
1597 8a7ddc38 bellard
        cpu_get_seg(f, &env->segs[i]);
1598 8a7ddc38 bellard
    cpu_get_seg(f, &env->ldt);
1599 8a7ddc38 bellard
    cpu_get_seg(f, &env->tr);
1600 8a7ddc38 bellard
    cpu_get_seg(f, &env->gdt);
1601 8a7ddc38 bellard
    cpu_get_seg(f, &env->idt);
1602 8a7ddc38 bellard
    
1603 8a7ddc38 bellard
    qemu_get_be32s(f, &env->sysenter_cs);
1604 8a7ddc38 bellard
    qemu_get_be32s(f, &env->sysenter_esp);
1605 8a7ddc38 bellard
    qemu_get_be32s(f, &env->sysenter_eip);
1606 8a7ddc38 bellard
    
1607 8a7ddc38 bellard
    qemu_get_be32s(f, &env->cr[0]);
1608 8a7ddc38 bellard
    qemu_get_be32s(f, &env->cr[2]);
1609 8a7ddc38 bellard
    qemu_get_be32s(f, &env->cr[3]);
1610 8a7ddc38 bellard
    qemu_get_be32s(f, &env->cr[4]);
1611 8a7ddc38 bellard
    
1612 8a7ddc38 bellard
    for(i = 0; i < 8; i++)
1613 8a7ddc38 bellard
        qemu_get_be32s(f, &env->dr[i]);
1614 8a7ddc38 bellard
1615 8a7ddc38 bellard
    /* MMU */
1616 8a7ddc38 bellard
    qemu_get_be32s(f, &env->a20_mask);
1617 8a7ddc38 bellard
1618 8a7ddc38 bellard
    /* XXX: compute hflags from scratch, except for CPL and IIF */
1619 8a7ddc38 bellard
    env->hflags = hflags;
1620 8a7ddc38 bellard
    tlb_flush(env, 1);
1621 8a7ddc38 bellard
    return 0;
1622 8a7ddc38 bellard
}
1623 8a7ddc38 bellard
1624 a541f297 bellard
#elif defined(TARGET_PPC)
1625 a541f297 bellard
void cpu_save(QEMUFile *f, void *opaque)
1626 a541f297 bellard
{
1627 a541f297 bellard
}
1628 a541f297 bellard
1629 a541f297 bellard
int cpu_load(QEMUFile *f, void *opaque, int version_id)
1630 a541f297 bellard
{
1631 a541f297 bellard
    return 0;
1632 a541f297 bellard
}
1633 8a7ddc38 bellard
#else
1634 8a7ddc38 bellard
1635 8a7ddc38 bellard
#warning No CPU save/restore functions
1636 8a7ddc38 bellard
1637 8a7ddc38 bellard
#endif
1638 8a7ddc38 bellard
1639 8a7ddc38 bellard
/***********************************************************/
1640 8a7ddc38 bellard
/* ram save/restore */
1641 8a7ddc38 bellard
1642 8a7ddc38 bellard
/* we just avoid storing empty pages */
1643 8a7ddc38 bellard
static void ram_put_page(QEMUFile *f, const uint8_t *buf, int len)
1644 8a7ddc38 bellard
{
1645 8a7ddc38 bellard
    int i, v;
1646 8a7ddc38 bellard
1647 8a7ddc38 bellard
    v = buf[0];
1648 8a7ddc38 bellard
    for(i = 1; i < len; i++) {
1649 8a7ddc38 bellard
        if (buf[i] != v)
1650 8a7ddc38 bellard
            goto normal_save;
1651 8a7ddc38 bellard
    }
1652 8a7ddc38 bellard
    qemu_put_byte(f, 1);
1653 8a7ddc38 bellard
    qemu_put_byte(f, v);
1654 8a7ddc38 bellard
    return;
1655 8a7ddc38 bellard
 normal_save:
1656 8a7ddc38 bellard
    qemu_put_byte(f, 0); 
1657 8a7ddc38 bellard
    qemu_put_buffer(f, buf, len);
1658 8a7ddc38 bellard
}
1659 8a7ddc38 bellard
1660 8a7ddc38 bellard
static int ram_get_page(QEMUFile *f, uint8_t *buf, int len)
1661 8a7ddc38 bellard
{
1662 8a7ddc38 bellard
    int v;
1663 8a7ddc38 bellard
1664 8a7ddc38 bellard
    v = qemu_get_byte(f);
1665 8a7ddc38 bellard
    switch(v) {
1666 8a7ddc38 bellard
    case 0:
1667 8a7ddc38 bellard
        if (qemu_get_buffer(f, buf, len) != len)
1668 8a7ddc38 bellard
            return -EIO;
1669 8a7ddc38 bellard
        break;
1670 8a7ddc38 bellard
    case 1:
1671 8a7ddc38 bellard
        v = qemu_get_byte(f);
1672 8a7ddc38 bellard
        memset(buf, v, len);
1673 8a7ddc38 bellard
        break;
1674 8a7ddc38 bellard
    default:
1675 8a7ddc38 bellard
        return -EINVAL;
1676 8a7ddc38 bellard
    }
1677 8a7ddc38 bellard
    return 0;
1678 8a7ddc38 bellard
}
1679 8a7ddc38 bellard
1680 8a7ddc38 bellard
static void ram_save(QEMUFile *f, void *opaque)
1681 8a7ddc38 bellard
{
1682 8a7ddc38 bellard
    int i;
1683 8a7ddc38 bellard
    qemu_put_be32(f, phys_ram_size);
1684 8a7ddc38 bellard
    for(i = 0; i < phys_ram_size; i+= TARGET_PAGE_SIZE) {
1685 8a7ddc38 bellard
        ram_put_page(f, phys_ram_base + i, TARGET_PAGE_SIZE);
1686 8a7ddc38 bellard
    }
1687 8a7ddc38 bellard
}
1688 8a7ddc38 bellard
1689 8a7ddc38 bellard
static int ram_load(QEMUFile *f, void *opaque, int version_id)
1690 8a7ddc38 bellard
{
1691 8a7ddc38 bellard
    int i, ret;
1692 8a7ddc38 bellard
1693 8a7ddc38 bellard
    if (version_id != 1)
1694 8a7ddc38 bellard
        return -EINVAL;
1695 8a7ddc38 bellard
    if (qemu_get_be32(f) != phys_ram_size)
1696 8a7ddc38 bellard
        return -EINVAL;
1697 8a7ddc38 bellard
    for(i = 0; i < phys_ram_size; i+= TARGET_PAGE_SIZE) {
1698 8a7ddc38 bellard
        ret = ram_get_page(f, phys_ram_base + i, TARGET_PAGE_SIZE);
1699 8a7ddc38 bellard
        if (ret)
1700 8a7ddc38 bellard
            return ret;
1701 8a7ddc38 bellard
    }
1702 8a7ddc38 bellard
    return 0;
1703 8a7ddc38 bellard
}
1704 8a7ddc38 bellard
1705 8a7ddc38 bellard
/***********************************************************/
1706 8a7ddc38 bellard
/* main execution loop */
1707 8a7ddc38 bellard
1708 8a7ddc38 bellard
void gui_update(void *opaque)
1709 8a7ddc38 bellard
{
1710 8a7ddc38 bellard
    display_state.dpy_refresh(&display_state);
1711 8a7ddc38 bellard
    qemu_mod_timer(gui_timer, GUI_REFRESH_INTERVAL + qemu_get_clock(rt_clock));
1712 8a7ddc38 bellard
}
1713 8a7ddc38 bellard
1714 8a7ddc38 bellard
/* XXX: support several handlers */
1715 8a7ddc38 bellard
VMStopHandler *vm_stop_cb;
1716 8a7ddc38 bellard
VMStopHandler *vm_stop_opaque;
1717 8a7ddc38 bellard
1718 8a7ddc38 bellard
int qemu_add_vm_stop_handler(VMStopHandler *cb, void *opaque)
1719 8a7ddc38 bellard
{
1720 8a7ddc38 bellard
    vm_stop_cb = cb;
1721 8a7ddc38 bellard
    vm_stop_opaque = opaque;
1722 8a7ddc38 bellard
    return 0;
1723 8a7ddc38 bellard
}
1724 8a7ddc38 bellard
1725 8a7ddc38 bellard
void qemu_del_vm_stop_handler(VMStopHandler *cb, void *opaque)
1726 8a7ddc38 bellard
{
1727 8a7ddc38 bellard
    vm_stop_cb = NULL;
1728 8a7ddc38 bellard
}
1729 8a7ddc38 bellard
1730 8a7ddc38 bellard
void vm_start(void)
1731 8a7ddc38 bellard
{
1732 8a7ddc38 bellard
    if (!vm_running) {
1733 8a7ddc38 bellard
        cpu_enable_ticks();
1734 8a7ddc38 bellard
        vm_running = 1;
1735 8a7ddc38 bellard
    }
1736 8a7ddc38 bellard
}
1737 8a7ddc38 bellard
1738 8a7ddc38 bellard
void vm_stop(int reason) 
1739 8a7ddc38 bellard
{
1740 8a7ddc38 bellard
    if (vm_running) {
1741 8a7ddc38 bellard
        cpu_disable_ticks();
1742 8a7ddc38 bellard
        vm_running = 0;
1743 8a7ddc38 bellard
        if (reason != 0) {
1744 8a7ddc38 bellard
            if (vm_stop_cb) {
1745 8a7ddc38 bellard
                vm_stop_cb(vm_stop_opaque, reason);
1746 8a7ddc38 bellard
            }
1747 34865134 bellard
        }
1748 8a7ddc38 bellard
    }
1749 8a7ddc38 bellard
}
1750 8a7ddc38 bellard
1751 8a7ddc38 bellard
int main_loop(void)
1752 8a7ddc38 bellard
{
1753 67b915a5 bellard
#ifndef _WIN32
1754 8a7ddc38 bellard
    struct pollfd ufds[MAX_IO_HANDLERS + 1], *pf;
1755 8a7ddc38 bellard
    IOHandlerRecord *ioh, *ioh_next;
1756 67b915a5 bellard
    uint8_t buf[4096];
1757 67b915a5 bellard
    int n, max_size;
1758 67b915a5 bellard
#endif
1759 67b915a5 bellard
    int ret, timeout;
1760 8a7ddc38 bellard
    CPUState *env = global_env;
1761 8a7ddc38 bellard
1762 8a7ddc38 bellard
    for(;;) {
1763 8a7ddc38 bellard
        if (vm_running) {
1764 8a7ddc38 bellard
            ret = cpu_exec(env);
1765 8a7ddc38 bellard
            if (reset_requested) {
1766 8a7ddc38 bellard
                ret = EXCP_INTERRUPT; 
1767 8a7ddc38 bellard
                break;
1768 8a7ddc38 bellard
            }
1769 8a7ddc38 bellard
            if (ret == EXCP_DEBUG) {
1770 8a7ddc38 bellard
                vm_stop(EXCP_DEBUG);
1771 8a7ddc38 bellard
            }
1772 8a7ddc38 bellard
            /* if hlt instruction, we wait until the next IRQ */
1773 8a7ddc38 bellard
            /* XXX: use timeout computed from timers */
1774 8a7ddc38 bellard
            if (ret == EXCP_HLT) 
1775 8a7ddc38 bellard
                timeout = 10;
1776 8a7ddc38 bellard
            else
1777 8a7ddc38 bellard
                timeout = 0;
1778 8a7ddc38 bellard
        } else {
1779 b4608c04 bellard
            timeout = 10;
1780 8a7ddc38 bellard
        }
1781 c4b1fcc0 bellard
1782 38e205a2 bellard
#ifdef _WIN32
1783 38e205a2 bellard
        if (timeout > 0)
1784 38e205a2 bellard
            Sleep(timeout);
1785 38e205a2 bellard
#else
1786 38e205a2 bellard
1787 b4608c04 bellard
        /* poll any events */
1788 8a7ddc38 bellard
        /* XXX: separate device handlers from system ones */
1789 b4608c04 bellard
        pf = ufds;
1790 8a7ddc38 bellard
        for(ioh = first_io_handler; ioh != NULL; ioh = ioh->next) {
1791 8a7ddc38 bellard
            if (!ioh->fd_can_read) {
1792 8a7ddc38 bellard
                max_size = 0;
1793 c4b1fcc0 bellard
                pf->fd = ioh->fd;
1794 c4b1fcc0 bellard
                pf->events = POLLIN;
1795 c4b1fcc0 bellard
                ioh->ufd = pf;
1796 c4b1fcc0 bellard
                pf++;
1797 c4b1fcc0 bellard
            } else {
1798 8a7ddc38 bellard
                max_size = ioh->fd_can_read(ioh->opaque);
1799 8a7ddc38 bellard
                if (max_size > 0) {
1800 8a7ddc38 bellard
                    if (max_size > sizeof(buf))
1801 8a7ddc38 bellard
                        max_size = sizeof(buf);
1802 8a7ddc38 bellard
                    pf->fd = ioh->fd;
1803 8a7ddc38 bellard
                    pf->events = POLLIN;
1804 8a7ddc38 bellard
                    ioh->ufd = pf;
1805 8a7ddc38 bellard
                    pf++;
1806 8a7ddc38 bellard
                } else {
1807 8a7ddc38 bellard
                    ioh->ufd = NULL;
1808 8a7ddc38 bellard
                }
1809 c4b1fcc0 bellard
            }
1810 c4b1fcc0 bellard
            ioh->max_size = max_size;
1811 b4608c04 bellard
        }
1812 73332e5c bellard
        
1813 b4608c04 bellard
        ret = poll(ufds, pf - ufds, timeout);
1814 b4608c04 bellard
        if (ret > 0) {
1815 8a7ddc38 bellard
            /* XXX: better handling of removal */
1816 8a7ddc38 bellard
            for(ioh = first_io_handler; ioh != NULL; ioh = ioh_next) {
1817 8a7ddc38 bellard
                ioh_next = ioh->next;
1818 c4b1fcc0 bellard
                pf = ioh->ufd;
1819 c4b1fcc0 bellard
                if (pf) {
1820 8a7ddc38 bellard
                    if (pf->revents & POLLIN) {
1821 8a7ddc38 bellard
                        if (ioh->max_size == 0) {
1822 8a7ddc38 bellard
                            /* just a read event */
1823 8a7ddc38 bellard
                            ioh->fd_read(ioh->opaque, NULL, 0);
1824 8a7ddc38 bellard
                        } else {
1825 8a7ddc38 bellard
                            n = read(ioh->fd, buf, ioh->max_size);
1826 8a7ddc38 bellard
                            if (n >= 0) {
1827 8a7ddc38 bellard
                                ioh->fd_read(ioh->opaque, buf, n);
1828 8a7ddc38 bellard
                            } else if (errno != -EAGAIN) {
1829 8a7ddc38 bellard
                                ioh->fd_read(ioh->opaque, NULL, -errno);
1830 8a7ddc38 bellard
                            }
1831 8a7ddc38 bellard
                        }
1832 b4608c04 bellard
                    }
1833 b4608c04 bellard
                }
1834 b4608c04 bellard
            }
1835 b4608c04 bellard
        }
1836 c20709aa bellard
1837 c20709aa bellard
#if defined(CONFIG_SLIRP)
1838 c20709aa bellard
        /* XXX: merge with poll() */
1839 c20709aa bellard
        if (slirp_inited) {
1840 c20709aa bellard
            fd_set rfds, wfds, xfds;
1841 c20709aa bellard
            int nfds;
1842 c20709aa bellard
            struct timeval tv;
1843 c20709aa bellard
1844 c20709aa bellard
            nfds = -1;
1845 c20709aa bellard
            FD_ZERO(&rfds);
1846 c20709aa bellard
            FD_ZERO(&wfds);
1847 c20709aa bellard
            FD_ZERO(&xfds);
1848 c20709aa bellard
            slirp_select_fill(&nfds, &rfds, &wfds, &xfds);
1849 c20709aa bellard
            tv.tv_sec = 0;
1850 c20709aa bellard
            tv.tv_usec = 0;
1851 c20709aa bellard
            ret = select(nfds + 1, &rfds, &wfds, &xfds, &tv);
1852 c20709aa bellard
            if (ret >= 0) {
1853 c20709aa bellard
                slirp_select_poll(&rfds, &wfds, &xfds);
1854 c20709aa bellard
            }
1855 c20709aa bellard
        }
1856 c20709aa bellard
#endif
1857 c20709aa bellard
1858 67b915a5 bellard
#endif
1859 b4608c04 bellard
1860 8a7ddc38 bellard
        if (vm_running) {
1861 8a7ddc38 bellard
            qemu_run_timers(&active_timers[QEMU_TIMER_VIRTUAL], 
1862 8a7ddc38 bellard
                            qemu_get_clock(vm_clock));
1863 8a7ddc38 bellard
            
1864 aaaa7df6 bellard
            if (audio_enabled) {
1865 aaaa7df6 bellard
                /* XXX: add explicit timer */
1866 aaaa7df6 bellard
                SB16_run();
1867 aaaa7df6 bellard
            }
1868 8a7ddc38 bellard
            
1869 8a7ddc38 bellard
            /* run dma transfers, if any */
1870 8a7ddc38 bellard
            DMA_run();
1871 b4608c04 bellard
        }
1872 313aa567 bellard
1873 8a7ddc38 bellard
        /* real time timers */
1874 8a7ddc38 bellard
        qemu_run_timers(&active_timers[QEMU_TIMER_REALTIME], 
1875 8a7ddc38 bellard
                        qemu_get_clock(rt_clock));
1876 b4608c04 bellard
    }
1877 34865134 bellard
    cpu_disable_ticks();
1878 34865134 bellard
    return ret;
1879 b4608c04 bellard
}
1880 b4608c04 bellard
1881 0824d6fc bellard
void help(void)
1882 0824d6fc bellard
{
1883 aaaa7df6 bellard
    printf("QEMU PC emulator version " QEMU_VERSION ", Copyright (c) 2003-2004 Fabrice Bellard\n"
1884 0db63474 bellard
           "usage: %s [options] [disk_image]\n"
1885 0824d6fc bellard
           "\n"
1886 a20dd508 bellard
           "'disk_image' is a raw hard image image for IDE hard disk 0\n"
1887 fc01f7e7 bellard
           "\n"
1888 a20dd508 bellard
           "Standard options:\n"
1889 c45886db bellard
           "-fda/-fdb file  use 'file' as floppy disk 0/1 image\n"
1890 36b486bb bellard
           "-hda/-hdb file  use 'file' as IDE hard disk 0/1 image\n"
1891 36b486bb bellard
           "-hdc/-hdd file  use 'file' as IDE hard disk 2/3 image\n"
1892 c4b1fcc0 bellard
           "-cdrom file     use 'file' as IDE cdrom image (cdrom is ide1 master)\n"
1893 6e44ba7f bellard
           "-boot [a|b|c|d] boot on floppy (a, b), hard disk (c) or CD-ROM (d)\n"
1894 a20dd508 bellard
           "-snapshot       write to temporary files instead of disk image files\n"
1895 a20dd508 bellard
           "-m megs         set virtual RAM size to megs MB\n"
1896 c4b1fcc0 bellard
           "-nographic      disable graphical output and redirect serial I/Os to console\n"
1897 aaaa7df6 bellard
           "-enable-audio   enable audio support\n"
1898 c4b1fcc0 bellard
           "\n"
1899 c4b1fcc0 bellard
           "Network options:\n"
1900 c20709aa bellard
           "-nics n         simulate 'n' network cards [default=1]\n"
1901 702c651c bellard
           "-macaddr addr   set the mac address of the first interface\n"
1902 c20709aa bellard
           "-n script       set tap/tun network init script [default=%s]\n"
1903 c20709aa bellard
           "-tun-fd fd      use this fd as already opened tap/tun interface\n"
1904 c20709aa bellard
#ifdef CONFIG_SLIRP
1905 c20709aa bellard
           "-user-net       use user mode network stack [default if no tap/tun script]\n"
1906 c20709aa bellard
#endif
1907 c20709aa bellard
           "-dummy-net      use dummy network stack\n"
1908 a20dd508 bellard
           "\n"
1909 c4b1fcc0 bellard
           "Linux boot specific:\n"
1910 a20dd508 bellard
           "-kernel bzImage use 'bzImage' as kernel image\n"
1911 a20dd508 bellard
           "-append cmdline use 'cmdline' as kernel command line\n"
1912 a20dd508 bellard
           "-initrd file    use 'file' as initial ram disk\n"
1913 fc01f7e7 bellard
           "\n"
1914 330d0414 bellard
           "Debug/Expert options:\n"
1915 a20dd508 bellard
           "-s              wait gdb connection to port %d\n"
1916 a20dd508 bellard
           "-p port         change gdb connection port\n"
1917 f193c797 bellard
           "-d item1,...    output log to %s (use -d ? for a list of log items)\n"
1918 a20dd508 bellard
           "-hdachs c,h,s   force hard disk 0 geometry (usually qemu can guess it)\n"
1919 a20dd508 bellard
           "-L path         set the directory for the BIOS and VGA BIOS\n"
1920 77fef8c1 bellard
#ifdef USE_CODE_COPY
1921 77fef8c1 bellard
           "-no-code-copy   disable code copy acceleration\n"
1922 77fef8c1 bellard
#endif
1923 77fef8c1 bellard
1924 0824d6fc bellard
           "\n"
1925 f1510b2c bellard
           "During emulation, use C-a h to get terminal commands:\n",
1926 0db63474 bellard
#ifdef CONFIG_SOFTMMU
1927 0db63474 bellard
           "qemu",
1928 0db63474 bellard
#else
1929 0db63474 bellard
           "qemu-fast",
1930 0db63474 bellard
#endif
1931 0db63474 bellard
           DEFAULT_NETWORK_SCRIPT, 
1932 6e44ba7f bellard
           DEFAULT_GDBSTUB_PORT,
1933 6e44ba7f bellard
           "/tmp/qemu.log");
1934 0824d6fc bellard
    term_print_help();
1935 0db63474 bellard
#ifndef CONFIG_SOFTMMU
1936 0db63474 bellard
    printf("\n"
1937 0db63474 bellard
           "NOTE: this version of QEMU is faster but it needs slightly patched OSes to\n"
1938 0db63474 bellard
           "work. Please use the 'qemu' executable to have a more accurate (but slower)\n"
1939 0db63474 bellard
           "PC emulation.\n");
1940 0db63474 bellard
#endif
1941 0824d6fc bellard
    exit(1);
1942 0824d6fc bellard
}
1943 0824d6fc bellard
1944 fc01f7e7 bellard
struct option long_options[] = {
1945 fc01f7e7 bellard
    { "initrd", 1, NULL, 0, },
1946 fc01f7e7 bellard
    { "hda", 1, NULL, 0, },
1947 fc01f7e7 bellard
    { "hdb", 1, NULL, 0, },
1948 33e3963e bellard
    { "snapshot", 0, NULL, 0, },
1949 330d0414 bellard
    { "hdachs", 1, NULL, 0, },
1950 a20dd508 bellard
    { "nographic", 0, NULL, 0, },
1951 a20dd508 bellard
    { "kernel", 1, NULL, 0, },
1952 a20dd508 bellard
    { "append", 1, NULL, 0, },
1953 42f1e0e4 bellard
    { "tun-fd", 1, NULL, 0, },
1954 36b486bb bellard
    { "hdc", 1, NULL, 0, },
1955 36b486bb bellard
    { "hdd", 1, NULL, 0, },
1956 36b486bb bellard
    { "cdrom", 1, NULL, 0, },
1957 36b486bb bellard
    { "boot", 1, NULL, 0, },
1958 c45886db bellard
    { "fda", 1, NULL, 0, },
1959 c45886db bellard
    { "fdb", 1, NULL, 0, },
1960 c4b1fcc0 bellard
    { "no-code-copy", 0, NULL, 0 },
1961 c4b1fcc0 bellard
    { "nics", 1, NULL, 0 },
1962 702c651c bellard
    { "macaddr", 1, NULL, 0 },
1963 f6bac380 bellard
    { "user-net", 0, NULL, 0 },
1964 f6bac380 bellard
    { "dummy-net", 0, NULL, 0 },
1965 aaaa7df6 bellard
    { "enable-audio", 0, NULL, 0 },
1966 fc01f7e7 bellard
    { NULL, 0, NULL, 0 },
1967 fc01f7e7 bellard
};
1968 fc01f7e7 bellard
1969 77fef8c1 bellard
#if defined (TARGET_I386) && defined(USE_CODE_COPY)
1970 77fef8c1 bellard
1971 77fef8c1 bellard
/* this stack is only used during signal handling */
1972 77fef8c1 bellard
#define SIGNAL_STACK_SIZE 32768
1973 77fef8c1 bellard
1974 77fef8c1 bellard
static uint8_t *signal_stack;
1975 77fef8c1 bellard
1976 77fef8c1 bellard
#endif
1977 77fef8c1 bellard
1978 c20709aa bellard
#define NET_IF_TUN   0
1979 c20709aa bellard
#define NET_IF_USER  1
1980 c20709aa bellard
#define NET_IF_DUMMY 2
1981 c20709aa bellard
1982 0824d6fc bellard
int main(int argc, char **argv)
1983 0824d6fc bellard
{
1984 67b915a5 bellard
#ifdef CONFIG_GDBSTUB
1985 67b915a5 bellard
    int use_gdbstub, gdbstub_port;
1986 67b915a5 bellard
#endif
1987 67b915a5 bellard
    int c, i, long_index, has_cdrom;
1988 1ccde1cb bellard
    int snapshot, linux_boot;
1989 c45886db bellard
    CPUState *env;
1990 7f7f9873 bellard
    const char *initrd_filename;
1991 c45886db bellard
    const char *hd_filename[MAX_DISKS], *fd_filename[MAX_FD];
1992 a20dd508 bellard
    const char *kernel_filename, *kernel_cmdline;
1993 313aa567 bellard
    DisplayState *ds = &display_state;
1994 c4b1fcc0 bellard
    int cyls, heads, secs;
1995 a541f297 bellard
    int start_emulation = 1;
1996 702c651c bellard
    uint8_t macaddr[6];
1997 c20709aa bellard
    int net_if_type, nb_tun_fds, tun_fds[MAX_NICS];
1998 c20709aa bellard
    
1999 67b915a5 bellard
#if !defined(CONFIG_SOFTMMU)
2000 0824d6fc bellard
    /* we never want that malloc() uses mmap() */
2001 0824d6fc bellard
    mallopt(M_MMAP_THRESHOLD, 4096 * 1024);
2002 67b915a5 bellard
#endif
2003 fc01f7e7 bellard
    initrd_filename = NULL;
2004 c45886db bellard
    for(i = 0; i < MAX_FD; i++)
2005 c45886db bellard
        fd_filename[i] = NULL;
2006 fc01f7e7 bellard
    for(i = 0; i < MAX_DISKS; i++)
2007 fc01f7e7 bellard
        hd_filename[i] = NULL;
2008 1ccde1cb bellard
    ram_size = 32 * 1024 * 1024;
2009 313aa567 bellard
    vga_ram_size = VGA_RAM_SIZE;
2010 f1510b2c bellard
    pstrcpy(network_script, sizeof(network_script), DEFAULT_NETWORK_SCRIPT);
2011 67b915a5 bellard
#ifdef CONFIG_GDBSTUB
2012 b4608c04 bellard
    use_gdbstub = 0;
2013 b4608c04 bellard
    gdbstub_port = DEFAULT_GDBSTUB_PORT;
2014 67b915a5 bellard
#endif
2015 33e3963e bellard
    snapshot = 0;
2016 a20dd508 bellard
    nographic = 0;
2017 a20dd508 bellard
    kernel_filename = NULL;
2018 a20dd508 bellard
    kernel_cmdline = "";
2019 c4b1fcc0 bellard
    has_cdrom = 1;
2020 c4b1fcc0 bellard
    cyls = heads = secs = 0;
2021 c4b1fcc0 bellard
2022 c20709aa bellard
    nb_tun_fds = 0;
2023 c20709aa bellard
    net_if_type = -1;
2024 c4b1fcc0 bellard
    nb_nics = 1;
2025 702c651c bellard
    /* default mac address of the first network interface */
2026 702c651c bellard
    macaddr[0] = 0x52;
2027 702c651c bellard
    macaddr[1] = 0x54;
2028 702c651c bellard
    macaddr[2] = 0x00;
2029 702c651c bellard
    macaddr[3] = 0x12;
2030 702c651c bellard
    macaddr[4] = 0x34;
2031 702c651c bellard
    macaddr[5] = 0x56;
2032 c20709aa bellard
2033 c20709aa bellard
2034 0824d6fc bellard
    for(;;) {
2035 a541f297 bellard
        c = getopt_long_only(argc, argv, "hm:d:n:sp:L:S", long_options, &long_index);
2036 0824d6fc bellard
        if (c == -1)
2037 0824d6fc bellard
            break;
2038 0824d6fc bellard
        switch(c) {
2039 fc01f7e7 bellard
        case 0:
2040 fc01f7e7 bellard
            switch(long_index) {
2041 fc01f7e7 bellard
            case 0:
2042 fc01f7e7 bellard
                initrd_filename = optarg;
2043 fc01f7e7 bellard
                break;
2044 fc01f7e7 bellard
            case 1:
2045 fc01f7e7 bellard
                hd_filename[0] = optarg;
2046 fc01f7e7 bellard
                break;
2047 fc01f7e7 bellard
            case 2:
2048 fc01f7e7 bellard
                hd_filename[1] = optarg;
2049 fc01f7e7 bellard
                break;
2050 33e3963e bellard
            case 3:
2051 33e3963e bellard
                snapshot = 1;
2052 33e3963e bellard
                break;
2053 330d0414 bellard
            case 4:
2054 330d0414 bellard
                {
2055 330d0414 bellard
                    const char *p;
2056 330d0414 bellard
                    p = optarg;
2057 330d0414 bellard
                    cyls = strtol(p, (char **)&p, 0);
2058 330d0414 bellard
                    if (*p != ',')
2059 330d0414 bellard
                        goto chs_fail;
2060 330d0414 bellard
                    p++;
2061 330d0414 bellard
                    heads = strtol(p, (char **)&p, 0);
2062 330d0414 bellard
                    if (*p != ',')
2063 330d0414 bellard
                        goto chs_fail;
2064 330d0414 bellard
                    p++;
2065 330d0414 bellard
                    secs = strtol(p, (char **)&p, 0);
2066 c4b1fcc0 bellard
                    if (*p != '\0') {
2067 c4b1fcc0 bellard
                    chs_fail:
2068 c4b1fcc0 bellard
                        cyls = 0;
2069 c4b1fcc0 bellard
                    }
2070 330d0414 bellard
                }
2071 330d0414 bellard
                break;
2072 313aa567 bellard
            case 5:
2073 a20dd508 bellard
                nographic = 1;
2074 a20dd508 bellard
                break;
2075 a20dd508 bellard
            case 6:
2076 a20dd508 bellard
                kernel_filename = optarg;
2077 a20dd508 bellard
                break;
2078 a20dd508 bellard
            case 7:
2079 a20dd508 bellard
                kernel_cmdline = optarg;
2080 313aa567 bellard
                break;
2081 42f1e0e4 bellard
            case 8:
2082 c4b1fcc0 bellard
                {
2083 c4b1fcc0 bellard
                    const char *p;
2084 c4b1fcc0 bellard
                    int fd;
2085 c20709aa bellard
                    if (nb_tun_fds < MAX_NICS) {
2086 c20709aa bellard
                        fd = strtol(optarg, (char **)&p, 0);
2087 c20709aa bellard
                        if (*p != '\0') {
2088 c20709aa bellard
                            fprintf(stderr, "qemu: invalid fd for network interface %d\n", nb_tun_fds);
2089 c4b1fcc0 bellard
                            exit(1);
2090 c4b1fcc0 bellard
                        }
2091 c20709aa bellard
                        tun_fds[nb_tun_fds++] = fd;
2092 c4b1fcc0 bellard
                    }
2093 c4b1fcc0 bellard
                }
2094 42f1e0e4 bellard
                break;
2095 36b486bb bellard
            case 9:
2096 36b486bb bellard
                hd_filename[2] = optarg;
2097 c4b1fcc0 bellard
                has_cdrom = 0;
2098 36b486bb bellard
                break;
2099 36b486bb bellard
            case 10:
2100 36b486bb bellard
                hd_filename[3] = optarg;
2101 36b486bb bellard
                break;
2102 36b486bb bellard
            case 11:
2103 36b486bb bellard
                hd_filename[2] = optarg;
2104 c4b1fcc0 bellard
                has_cdrom = 1;
2105 36b486bb bellard
                break;
2106 36b486bb bellard
            case 12:
2107 36b486bb bellard
                boot_device = optarg[0];
2108 c45886db bellard
                if (boot_device != 'a' && boot_device != 'b' &&
2109 c45886db bellard
                    boot_device != 'c' && boot_device != 'd') {
2110 36b486bb bellard
                    fprintf(stderr, "qemu: invalid boot device '%c'\n", boot_device);
2111 36b486bb bellard
                    exit(1);
2112 36b486bb bellard
                }
2113 36b486bb bellard
                break;
2114 c45886db bellard
            case 13:
2115 c45886db bellard
                fd_filename[0] = optarg;
2116 c45886db bellard
                break;
2117 c45886db bellard
            case 14:
2118 c45886db bellard
                fd_filename[1] = optarg;
2119 c45886db bellard
                break;
2120 77fef8c1 bellard
            case 15:
2121 77fef8c1 bellard
                code_copy_enabled = 0;
2122 77fef8c1 bellard
                break;
2123 c4b1fcc0 bellard
            case 16:
2124 c4b1fcc0 bellard
                nb_nics = atoi(optarg);
2125 c4b1fcc0 bellard
                if (nb_nics < 1 || nb_nics > MAX_NICS) {
2126 c4b1fcc0 bellard
                    fprintf(stderr, "qemu: invalid number of network interfaces\n");
2127 c4b1fcc0 bellard
                    exit(1);
2128 c4b1fcc0 bellard
                }
2129 c4b1fcc0 bellard
                break;
2130 702c651c bellard
            case 17:
2131 702c651c bellard
                {
2132 702c651c bellard
                    const char *p;
2133 702c651c bellard
                    int i;
2134 702c651c bellard
                    p = optarg;
2135 702c651c bellard
                    for(i = 0; i < 6; i++) {
2136 702c651c bellard
                        macaddr[i] = strtol(p, (char **)&p, 16);
2137 702c651c bellard
                        if (i == 5) {
2138 702c651c bellard
                            if (*p != '\0') 
2139 702c651c bellard
                                goto macaddr_error;
2140 702c651c bellard
                        } else {
2141 702c651c bellard
                            if (*p != ':') {
2142 702c651c bellard
                            macaddr_error:
2143 702c651c bellard
                                fprintf(stderr, "qemu: invalid syntax for ethernet address\n");
2144 702c651c bellard
                                exit(1);
2145 702c651c bellard
                            }
2146 702c651c bellard
                            p++;
2147 702c651c bellard
                        }
2148 702c651c bellard
                    }
2149 702c651c bellard
                }
2150 702c651c bellard
                break;
2151 c20709aa bellard
            case 18:
2152 c20709aa bellard
                net_if_type = NET_IF_USER;
2153 c20709aa bellard
                break;
2154 c20709aa bellard
            case 19:
2155 c20709aa bellard
                net_if_type = NET_IF_DUMMY;
2156 c20709aa bellard
                break;
2157 aaaa7df6 bellard
            case 20:
2158 aaaa7df6 bellard
                audio_enabled = 1;
2159 aaaa7df6 bellard
                break;
2160 fc01f7e7 bellard
            }
2161 fc01f7e7 bellard
            break;
2162 0824d6fc bellard
        case 'h':
2163 0824d6fc bellard
            help();
2164 0824d6fc bellard
            break;
2165 0824d6fc bellard
        case 'm':
2166 1ccde1cb bellard
            ram_size = atoi(optarg) * 1024 * 1024;
2167 1ccde1cb bellard
            if (ram_size <= 0)
2168 0824d6fc bellard
                help();
2169 1ccde1cb bellard
            if (ram_size > PHYS_RAM_MAX_SIZE) {
2170 36b486bb bellard
                fprintf(stderr, "qemu: at most %d MB RAM can be simulated\n",
2171 7916e224 bellard
                        PHYS_RAM_MAX_SIZE / (1024 * 1024));
2172 7916e224 bellard
                exit(1);
2173 7916e224 bellard
            }
2174 0824d6fc bellard
            break;
2175 0824d6fc bellard
        case 'd':
2176 f193c797 bellard
            {
2177 f193c797 bellard
                int mask;
2178 f193c797 bellard
                CPULogItem *item;
2179 f193c797 bellard
2180 f193c797 bellard
                mask = cpu_str_to_log_mask(optarg);
2181 f193c797 bellard
                if (!mask) {
2182 f193c797 bellard
                    printf("Log items (comma separated):\n");
2183 f193c797 bellard
                    for(item = cpu_log_items; item->mask != 0; item++) {
2184 f193c797 bellard
                        printf("%-10s %s\n", item->name, item->help);
2185 f193c797 bellard
                    }
2186 f193c797 bellard
                    exit(1);
2187 f193c797 bellard
                }
2188 f193c797 bellard
                cpu_set_log(mask);
2189 f193c797 bellard
            }
2190 0824d6fc bellard
            break;
2191 f1510b2c bellard
        case 'n':
2192 f1510b2c bellard
            pstrcpy(network_script, sizeof(network_script), optarg);
2193 f1510b2c bellard
            break;
2194 67b915a5 bellard
#ifdef CONFIG_GDBSTUB
2195 b4608c04 bellard
        case 's':
2196 b4608c04 bellard
            use_gdbstub = 1;
2197 b4608c04 bellard
            break;
2198 b4608c04 bellard
        case 'p':
2199 b4608c04 bellard
            gdbstub_port = atoi(optarg);
2200 b4608c04 bellard
            break;
2201 67b915a5 bellard
#endif
2202 330d0414 bellard
        case 'L':
2203 5a67135a bellard
            bios_dir = optarg;
2204 330d0414 bellard
            break;
2205 a541f297 bellard
        case 'S':
2206 a541f297 bellard
            start_emulation = 0;
2207 a541f297 bellard
            break;
2208 0824d6fc bellard
        }
2209 0824d6fc bellard
    }
2210 330d0414 bellard
2211 a20dd508 bellard
    if (optind < argc) {
2212 a20dd508 bellard
        hd_filename[0] = argv[optind++];
2213 a20dd508 bellard
    }
2214 a20dd508 bellard
2215 a20dd508 bellard
    linux_boot = (kernel_filename != NULL);
2216 330d0414 bellard
        
2217 c45886db bellard
    if (!linux_boot && hd_filename[0] == '\0' && hd_filename[2] == '\0' &&
2218 c45886db bellard
        fd_filename[0] == '\0')
2219 0824d6fc bellard
        help();
2220 8f2b1fb0 bellard
    
2221 8f2b1fb0 bellard
    /* boot to cd by default if no hard disk */
2222 d0309311 bellard
    if (hd_filename[0] == '\0' && boot_device == 'c') {
2223 d0309311 bellard
        if (fd_filename[0] != '\0')
2224 d0309311 bellard
            boot_device = 'a';
2225 d0309311 bellard
        else
2226 d0309311 bellard
            boot_device = 'd';
2227 d0309311 bellard
    }
2228 0824d6fc bellard
2229 dc887a4d bellard
#if !defined(CONFIG_SOFTMMU)
2230 dc887a4d bellard
    /* must avoid mmap() usage of glibc by setting a buffer "by hand" */
2231 dc887a4d bellard
    {
2232 dc887a4d bellard
        static uint8_t stdout_buf[4096];
2233 dc887a4d bellard
        setvbuf(stdout, stdout_buf, _IOLBF, sizeof(stdout_buf));
2234 dc887a4d bellard
    }
2235 dc887a4d bellard
#else
2236 b118d61e bellard
    setvbuf(stdout, NULL, _IOLBF, 0);
2237 dc887a4d bellard
#endif
2238 0824d6fc bellard
2239 c4b1fcc0 bellard
    /* init host network redirectors */
2240 c20709aa bellard
    if (net_if_type == -1) {
2241 c20709aa bellard
        net_if_type = NET_IF_TUN;
2242 c20709aa bellard
#if defined(CONFIG_SLIRP)
2243 c20709aa bellard
        if (access(network_script, R_OK) < 0) {
2244 c20709aa bellard
            net_if_type = NET_IF_USER;
2245 c20709aa bellard
        }
2246 c20709aa bellard
#endif
2247 c20709aa bellard
    }
2248 c20709aa bellard
2249 c20709aa bellard
    for(i = 0; i < nb_nics; i++) {
2250 702c651c bellard
        NetDriverState *nd = &nd_table[i];
2251 c20709aa bellard
        nd->index = i;
2252 702c651c bellard
        /* init virtual mac address */
2253 702c651c bellard
        nd->macaddr[0] = macaddr[0];
2254 702c651c bellard
        nd->macaddr[1] = macaddr[1];
2255 702c651c bellard
        nd->macaddr[2] = macaddr[2];
2256 702c651c bellard
        nd->macaddr[3] = macaddr[3];
2257 702c651c bellard
        nd->macaddr[4] = macaddr[4];
2258 702c651c bellard
        nd->macaddr[5] = macaddr[5] + i;
2259 c20709aa bellard
        switch(net_if_type) {
2260 c20709aa bellard
#if defined(CONFIG_SLIRP)
2261 c20709aa bellard
        case NET_IF_USER:
2262 c20709aa bellard
            net_slirp_init(nd);
2263 c20709aa bellard
            break;
2264 c20709aa bellard
#endif
2265 c20709aa bellard
#if !defined(_WIN32)
2266 c20709aa bellard
        case NET_IF_TUN:
2267 c20709aa bellard
            if (i < nb_tun_fds) {
2268 c20709aa bellard
                net_fd_init(nd, tun_fds[i]);
2269 c20709aa bellard
            } else {
2270 d927637d bellard
                if (net_tun_init(nd) < 0)
2271 d927637d bellard
                    net_dummy_init(nd);
2272 c20709aa bellard
            }
2273 c20709aa bellard
            break;
2274 c20709aa bellard
#endif
2275 c20709aa bellard
        case NET_IF_DUMMY:
2276 c20709aa bellard
        default:
2277 c20709aa bellard
            net_dummy_init(nd);
2278 c20709aa bellard
            break;
2279 c20709aa bellard
        }
2280 702c651c bellard
    }
2281 f1510b2c bellard
2282 0824d6fc bellard
    /* init the memory */
2283 1ccde1cb bellard
    phys_ram_size = ram_size + vga_ram_size;
2284 7f7f9873 bellard
2285 7f7f9873 bellard
#ifdef CONFIG_SOFTMMU
2286 7d3505c5 bellard
#ifdef _BSD
2287 7d3505c5 bellard
    /* mallocs are always aligned on BSD. */
2288 7d3505c5 bellard
    phys_ram_base = malloc(phys_ram_size);
2289 7d3505c5 bellard
#else
2290 1ccde1cb bellard
    phys_ram_base = memalign(TARGET_PAGE_SIZE, phys_ram_size);
2291 7d3505c5 bellard
#endif
2292 7f7f9873 bellard
    if (!phys_ram_base) {
2293 7f7f9873 bellard
        fprintf(stderr, "Could not allocate physical memory\n");
2294 0824d6fc bellard
        exit(1);
2295 0824d6fc bellard
    }
2296 7f7f9873 bellard
#else
2297 7f7f9873 bellard
    /* as we must map the same page at several addresses, we must use
2298 7f7f9873 bellard
       a fd */
2299 7f7f9873 bellard
    {
2300 7f7f9873 bellard
        const char *tmpdir;
2301 7f7f9873 bellard
2302 7f7f9873 bellard
        tmpdir = getenv("QEMU_TMPDIR");
2303 7f7f9873 bellard
        if (!tmpdir)
2304 7f7f9873 bellard
            tmpdir = "/tmp";
2305 7f7f9873 bellard
        snprintf(phys_ram_file, sizeof(phys_ram_file), "%s/vlXXXXXX", tmpdir);
2306 7f7f9873 bellard
        if (mkstemp(phys_ram_file) < 0) {
2307 7f7f9873 bellard
            fprintf(stderr, "Could not create temporary memory file '%s'\n", 
2308 7f7f9873 bellard
                    phys_ram_file);
2309 7f7f9873 bellard
            exit(1);
2310 7f7f9873 bellard
        }
2311 7f7f9873 bellard
        phys_ram_fd = open(phys_ram_file, O_CREAT | O_TRUNC | O_RDWR, 0600);
2312 7f7f9873 bellard
        if (phys_ram_fd < 0) {
2313 7f7f9873 bellard
            fprintf(stderr, "Could not open temporary memory file '%s'\n", 
2314 7f7f9873 bellard
                    phys_ram_file);
2315 7f7f9873 bellard
            exit(1);
2316 7f7f9873 bellard
        }
2317 1ccde1cb bellard
        ftruncate(phys_ram_fd, phys_ram_size);
2318 7f7f9873 bellard
        unlink(phys_ram_file);
2319 1ccde1cb bellard
        phys_ram_base = mmap(get_mmap_addr(phys_ram_size), 
2320 1ccde1cb bellard
                             phys_ram_size, 
2321 7f7f9873 bellard
                             PROT_WRITE | PROT_READ, MAP_SHARED | MAP_FIXED, 
2322 7f7f9873 bellard
                             phys_ram_fd, 0);
2323 7f7f9873 bellard
        if (phys_ram_base == MAP_FAILED) {
2324 7f7f9873 bellard
            fprintf(stderr, "Could not map physical memory\n");
2325 7f7f9873 bellard
            exit(1);
2326 7f7f9873 bellard
        }
2327 7f7f9873 bellard
    }
2328 7f7f9873 bellard
#endif
2329 0824d6fc bellard
2330 c4b1fcc0 bellard
    /* we always create the cdrom drive, even if no disk is there */
2331 c4b1fcc0 bellard
    if (has_cdrom) {
2332 c4b1fcc0 bellard
        bs_table[2] = bdrv_new("cdrom");
2333 c4b1fcc0 bellard
        bdrv_set_type_hint(bs_table[2], BDRV_TYPE_CDROM);
2334 c4b1fcc0 bellard
    }
2335 c4b1fcc0 bellard
2336 33e3963e bellard
    /* open the virtual block devices */
2337 33e3963e bellard
    for(i = 0; i < MAX_DISKS; i++) {
2338 33e3963e bellard
        if (hd_filename[i]) {
2339 33e3963e bellard
            if (!bs_table[i]) {
2340 c4b1fcc0 bellard
                char buf[64];
2341 c4b1fcc0 bellard
                snprintf(buf, sizeof(buf), "hd%c", i + 'a');
2342 c4b1fcc0 bellard
                bs_table[i] = bdrv_new(buf);
2343 c4b1fcc0 bellard
            }
2344 c4b1fcc0 bellard
            if (bdrv_open(bs_table[i], hd_filename[i], snapshot) < 0) {
2345 36b486bb bellard
                fprintf(stderr, "qemu: could not open hard disk image '%s\n",
2346 33e3963e bellard
                        hd_filename[i]);
2347 33e3963e bellard
                exit(1);
2348 33e3963e bellard
            }
2349 c4b1fcc0 bellard
            if (i == 0 && cyls != 0) 
2350 c4b1fcc0 bellard
                bdrv_set_geometry_hint(bs_table[i], cyls, heads, secs);
2351 c4b1fcc0 bellard
        }
2352 c4b1fcc0 bellard
    }
2353 c4b1fcc0 bellard
2354 c4b1fcc0 bellard
    /* we always create at least one floppy disk */
2355 c4b1fcc0 bellard
    fd_table[0] = bdrv_new("fda");
2356 c4b1fcc0 bellard
    bdrv_set_type_hint(fd_table[0], BDRV_TYPE_FLOPPY);
2357 c4b1fcc0 bellard
2358 c4b1fcc0 bellard
    for(i = 0; i < MAX_FD; i++) {
2359 c4b1fcc0 bellard
        if (fd_filename[i]) {
2360 c4b1fcc0 bellard
            if (!fd_table[i]) {
2361 c4b1fcc0 bellard
                char buf[64];
2362 c4b1fcc0 bellard
                snprintf(buf, sizeof(buf), "fd%c", i + 'a');
2363 c4b1fcc0 bellard
                fd_table[i] = bdrv_new(buf);
2364 c4b1fcc0 bellard
                bdrv_set_type_hint(fd_table[i], BDRV_TYPE_FLOPPY);
2365 c4b1fcc0 bellard
            }
2366 c4b1fcc0 bellard
            if (fd_filename[i] != '\0') {
2367 c4b1fcc0 bellard
                if (bdrv_open(fd_table[i], fd_filename[i], snapshot) < 0) {
2368 c20709aa bellard
                    fprintf(stderr, "qemu: could not open floppy disk image '%s'\n",
2369 c4b1fcc0 bellard
                            fd_filename[i]);
2370 c4b1fcc0 bellard
                    exit(1);
2371 c4b1fcc0 bellard
                }
2372 c4b1fcc0 bellard
            }
2373 33e3963e bellard
        }
2374 33e3963e bellard
    }
2375 33e3963e bellard
2376 330d0414 bellard
    /* init CPU state */
2377 330d0414 bellard
    env = cpu_init();
2378 330d0414 bellard
    global_env = env;
2379 330d0414 bellard
    cpu_single_env = env;
2380 330d0414 bellard
2381 8a7ddc38 bellard
    register_savevm("timer", 0, 1, timer_save, timer_load, env);
2382 8a7ddc38 bellard
    register_savevm("cpu", 0, 1, cpu_save, cpu_load, env);
2383 8a7ddc38 bellard
    register_savevm("ram", 0, 1, ram_save, ram_load, NULL);
2384 8a7ddc38 bellard
2385 330d0414 bellard
    init_ioports();
2386 80cabfad bellard
    cpu_calibrate_ticks();
2387 0824d6fc bellard
2388 313aa567 bellard
    /* terminal init */
2389 a20dd508 bellard
    if (nographic) {
2390 313aa567 bellard
        dumb_display_init(ds);
2391 313aa567 bellard
    } else {
2392 313aa567 bellard
#ifdef CONFIG_SDL
2393 313aa567 bellard
        sdl_display_init(ds);
2394 313aa567 bellard
#else
2395 313aa567 bellard
        dumb_display_init(ds);
2396 313aa567 bellard
#endif
2397 313aa567 bellard
    }
2398 0824d6fc bellard
2399 0824d6fc bellard
    /* setup cpu signal handlers for MMU / self modifying code handling */
2400 77fef8c1 bellard
#if !defined(CONFIG_SOFTMMU)
2401 8a7ddc38 bellard
    
2402 77fef8c1 bellard
#if defined (TARGET_I386) && defined(USE_CODE_COPY)
2403 77fef8c1 bellard
    {
2404 77fef8c1 bellard
        stack_t stk;
2405 73332e5c bellard
        signal_stack = memalign(16, SIGNAL_STACK_SIZE);
2406 77fef8c1 bellard
        stk.ss_sp = signal_stack;
2407 77fef8c1 bellard
        stk.ss_size = SIGNAL_STACK_SIZE;
2408 77fef8c1 bellard
        stk.ss_flags = 0;
2409 77fef8c1 bellard
2410 77fef8c1 bellard
        if (sigaltstack(&stk, NULL) < 0) {
2411 77fef8c1 bellard
            perror("sigaltstack");
2412 77fef8c1 bellard
            exit(1);
2413 77fef8c1 bellard
        }
2414 77fef8c1 bellard
    }
2415 77fef8c1 bellard
#endif
2416 8a7ddc38 bellard
    {
2417 8a7ddc38 bellard
        struct sigaction act;
2418 77fef8c1 bellard
        
2419 8a7ddc38 bellard
        sigfillset(&act.sa_mask);
2420 8a7ddc38 bellard
        act.sa_flags = SA_SIGINFO;
2421 77fef8c1 bellard
#if defined (TARGET_I386) && defined(USE_CODE_COPY)
2422 8a7ddc38 bellard
        act.sa_flags |= SA_ONSTACK;
2423 77fef8c1 bellard
#endif
2424 8a7ddc38 bellard
        act.sa_sigaction = host_segv_handler;
2425 8a7ddc38 bellard
        sigaction(SIGSEGV, &act, NULL);
2426 8a7ddc38 bellard
        sigaction(SIGBUS, &act, NULL);
2427 77fef8c1 bellard
#if defined (TARGET_I386) && defined(USE_CODE_COPY)
2428 8a7ddc38 bellard
        sigaction(SIGFPE, &act, NULL);
2429 77fef8c1 bellard
#endif
2430 8a7ddc38 bellard
    }
2431 3a51dee6 bellard
#endif
2432 0824d6fc bellard
2433 67b915a5 bellard
#ifndef _WIN32
2434 8a7ddc38 bellard
    {
2435 8a7ddc38 bellard
        struct sigaction act;
2436 8a7ddc38 bellard
        sigfillset(&act.sa_mask);
2437 8a7ddc38 bellard
        act.sa_flags = 0;
2438 8a7ddc38 bellard
        act.sa_handler = SIG_IGN;
2439 8a7ddc38 bellard
        sigaction(SIGPIPE, &act, NULL);
2440 8a7ddc38 bellard
    }
2441 67b915a5 bellard
#endif
2442 73332e5c bellard
    init_timers();
2443 73332e5c bellard
2444 73332e5c bellard
#if defined(TARGET_I386)
2445 73332e5c bellard
    pc_init(ram_size, vga_ram_size, boot_device,
2446 73332e5c bellard
            ds, fd_filename, snapshot,
2447 73332e5c bellard
            kernel_filename, kernel_cmdline, initrd_filename);
2448 73332e5c bellard
#elif defined(TARGET_PPC)
2449 a541f297 bellard
    ppc_init(ram_size, vga_ram_size, boot_device,
2450 a541f297 bellard
             ds, fd_filename, snapshot,
2451 a541f297 bellard
             kernel_filename, kernel_cmdline, initrd_filename);
2452 73332e5c bellard
#endif
2453 73332e5c bellard
2454 73332e5c bellard
    /* launched after the device init so that it can display or not a
2455 73332e5c bellard
       banner */
2456 73332e5c bellard
    monitor_init();
2457 0824d6fc bellard
2458 8a7ddc38 bellard
    gui_timer = qemu_new_timer(rt_clock, gui_update, NULL);
2459 8a7ddc38 bellard
    qemu_mod_timer(gui_timer, qemu_get_clock(rt_clock));
2460 7f7f9873 bellard
2461 67b915a5 bellard
#ifdef CONFIG_GDBSTUB
2462 b4608c04 bellard
    if (use_gdbstub) {
2463 8a7ddc38 bellard
        if (gdbserver_start(gdbstub_port) < 0) {
2464 8a7ddc38 bellard
            fprintf(stderr, "Could not open gdbserver socket on port %d\n", 
2465 8a7ddc38 bellard
                    gdbstub_port);
2466 8a7ddc38 bellard
            exit(1);
2467 8a7ddc38 bellard
        } else {
2468 8a7ddc38 bellard
            printf("Waiting gdb connection on port %d\n", gdbstub_port);
2469 8a7ddc38 bellard
        }
2470 67b915a5 bellard
    } else 
2471 67b915a5 bellard
#endif
2472 a541f297 bellard
    if (start_emulation)
2473 67b915a5 bellard
    {
2474 8a7ddc38 bellard
        vm_start();
2475 0824d6fc bellard
    }
2476 8a7ddc38 bellard
    term_init();
2477 8a7ddc38 bellard
    main_loop();
2478 40c3bac3 bellard
    quit_timers();
2479 0824d6fc bellard
    return 0;
2480 0824d6fc bellard
}