blob: 32474bfc79553f1d831de5f77f81be1c628e15ee [file] [log] [blame]
bellard0824d6f2003-06-24 13:42:40 +00001/*
bellard80cabfa2004-03-14 12:20:30 +00002 * QEMU System Emulator
bellard0824d6f2003-06-24 13:42:40 +00003 *
bellard80cabfa2004-03-14 12:20:30 +00004 * Copyright (c) 2003-2004 Fabrice Bellard
bellard0824d6f2003-06-24 13:42:40 +00005 *
bellard1df912c2003-06-25 16:20:35 +00006 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 * THE SOFTWARE.
bellard0824d6f2003-06-24 13:42:40 +000023 */
bellard67b915a2004-03-31 23:37:16 +000024#include "vl.h"
25
bellard0824d6f2003-06-24 13:42:40 +000026#include <unistd.h>
bellard0824d6f2003-06-24 13:42:40 +000027#include <fcntl.h>
28#include <signal.h>
29#include <time.h>
bellard0824d6f2003-06-24 13:42:40 +000030#include <errno.h>
bellard67b915a2004-03-31 23:37:16 +000031#include <sys/time.h>
32
33#ifndef _WIN32
34#include <sys/times.h>
bellardf1510b22003-06-25 00:07:40 +000035#include <sys/wait.h>
bellard67b915a2004-03-31 23:37:16 +000036#include <termios.h>
37#include <sys/poll.h>
38#include <sys/mman.h>
bellardf1510b22003-06-25 00:07:40 +000039#include <sys/ioctl.h>
40#include <sys/socket.h>
bellardc94c8d62004-09-13 21:37:34 +000041#include <netinet/in.h>
bellard9d728e82004-09-05 23:09:03 +000042#include <dirent.h>
bellard7d3505c2004-05-12 19:32:15 +000043#ifdef _BSD
44#include <sys/stat.h>
bellard83fb7ad2004-07-05 21:25:26 +000045#ifndef __APPLE__
bellard7d3505c2004-05-12 19:32:15 +000046#include <libutil.h>
bellard83fb7ad2004-07-05 21:25:26 +000047#endif
bellard7d3505c2004-05-12 19:32:15 +000048#else
bellardf1510b22003-06-25 00:07:40 +000049#include <linux/if.h>
50#include <linux/if_tun.h>
bellard7d3505c2004-05-12 19:32:15 +000051#include <pty.h>
52#include <malloc.h>
bellardfd872592004-05-12 19:11:15 +000053#include <linux/rtc.h>
bellard67b915a2004-03-31 23:37:16 +000054#endif
bellard7d3505c2004-05-12 19:32:15 +000055#endif
bellard67b915a2004-03-31 23:37:16 +000056
bellardc20709a2004-04-21 23:27:19 +000057#if defined(CONFIG_SLIRP)
58#include "libslirp.h"
59#endif
60
bellard67b915a2004-03-31 23:37:16 +000061#ifdef _WIN32
bellard7d3505c2004-05-12 19:32:15 +000062#include <malloc.h>
bellard67b915a2004-03-31 23:37:16 +000063#include <sys/timeb.h>
64#include <windows.h>
65#define getopt_long_only getopt_long
66#define memalign(align, size) malloc(size)
67#endif
68
bellard73332e52004-04-04 20:22:28 +000069#ifdef CONFIG_SDL
bellard96bcd4f2004-07-10 16:26:15 +000070#ifdef __APPLE__
bellard83fb7ad2004-07-05 21:25:26 +000071#include <SDL/SDL.h>
bellard96bcd4f2004-07-10 16:26:15 +000072#endif
bellard73332e52004-04-04 20:22:28 +000073#endif /* CONFIG_SDL */
bellard0824d6f2003-06-24 13:42:40 +000074
bellard0824d6f2003-06-24 13:42:40 +000075#include "disas.h"
bellardfc01f7e2003-06-30 10:03:06 +000076
bellard8a7ddc32004-03-31 19:00:16 +000077#include "exec-all.h"
bellard0824d6f2003-06-24 13:42:40 +000078
bellarda541f292004-04-12 20:39:29 +000079//#define DO_TB_FLUSH
80
bellard5a671352003-10-01 00:13:48 +000081#define DEFAULT_NETWORK_SCRIPT "/etc/qemu-ifup"
bellardf1510b22003-06-25 00:07:40 +000082
bellard0824d6f2003-06-24 13:42:40 +000083//#define DEBUG_UNUSED_IOPORT
bellardfd872592004-05-12 19:11:15 +000084//#define DEBUG_IOPORT
bellard330d0412003-07-26 18:11:40 +000085
bellardbb551fa2004-01-24 13:42:26 +000086#if !defined(CONFIG_SOFTMMU)
bellard7916e222003-07-01 16:27:45 +000087#define PHYS_RAM_MAX_SIZE (256 * 1024 * 1024)
bellardbb551fa2004-01-24 13:42:26 +000088#else
89#define PHYS_RAM_MAX_SIZE (2047 * 1024 * 1024)
90#endif
bellard7916e222003-07-01 16:27:45 +000091
bellard77d4bc32004-05-26 22:13:53 +000092#ifdef TARGET_PPC
93#define DEFAULT_RAM_SIZE 144
94#else
bellard1bfe8562004-07-08 21:17:50 +000095#define DEFAULT_RAM_SIZE 128
bellard77d4bc32004-05-26 22:13:53 +000096#endif
bellard8a7ddc32004-03-31 19:00:16 +000097/* in ms */
98#define GUI_REFRESH_INTERVAL 30
bellard313aa562003-08-10 21:52:11 +000099
bellard7dea1da2003-11-16 15:59:30 +0000100/* XXX: use a two level table to limit memory usage */
101#define MAX_IOPORTS 65536
bellard0824d6f2003-06-24 13:42:40 +0000102
bellard80cabfa2004-03-14 12:20:30 +0000103const char *bios_dir = CONFIG_QEMU_SHAREDIR;
bellard0824d6f2003-06-24 13:42:40 +0000104char phys_ram_file[1024];
bellardc45886d2004-01-05 00:02:06 +0000105CPUState *global_env;
106CPUState *cpu_single_env;
bellardc4b1fcc2004-03-14 21:44:30 +0000107void *ioport_opaque[MAX_IOPORTS];
bellardfc01f7e2003-06-30 10:03:06 +0000108IOPortReadFunc *ioport_read_table[3][MAX_IOPORTS];
109IOPortWriteFunc *ioport_write_table[3][MAX_IOPORTS];
bellardc45886d2004-01-05 00:02:06 +0000110BlockDriverState *bs_table[MAX_DISKS], *fd_table[MAX_FD];
bellard313aa562003-08-10 21:52:11 +0000111int vga_ram_size;
bellard0ced6582004-05-23 21:06:12 +0000112int bios_size;
bellard313aa562003-08-10 21:52:11 +0000113static DisplayState display_state;
bellarda20dd502003-09-30 21:07:02 +0000114int nographic;
bellard313aa562003-08-10 21:52:11 +0000115int64_t ticks_per_sec;
bellard36b486b2003-11-11 13:36:08 +0000116int boot_device = 'c';
bellard0ced6582004-05-23 21:06:12 +0000117int ram_size;
bellard80cabfa2004-03-14 12:20:30 +0000118static char network_script[1024];
119int pit_min_timer_count = 0;
bellardc4b1fcc2004-03-14 21:44:30 +0000120int nb_nics;
121NetDriverState nd_table[MAX_NICS];
bellard8a7ddc32004-03-31 19:00:16 +0000122QEMUTimer *gui_timer;
123int vm_running;
bellardaaaa7df2004-04-26 20:56:53 +0000124int audio_enabled = 0;
bellardbb0c6722004-06-20 12:37:32 +0000125int pci_enabled = 1;
bellard77d4bc32004-05-26 22:13:53 +0000126int prep_enabled = 0;
bellardee22c2f2004-06-03 12:49:50 +0000127int rtc_utc = 1;
bellard1bfe8562004-07-08 21:17:50 +0000128int cirrus_vga_enabled = 1;
129int graphic_width = 800;
130int graphic_height = 600;
bellarde9b137c2004-06-21 16:46:10 +0000131int graphic_depth = 15;
bellardd63d3072004-10-03 13:29:03 +0000132int full_screen = 0;
bellard82c643f2004-07-14 17:28:13 +0000133TextConsole *vga_console;
bellard8d11df92004-08-24 21:13:40 +0000134CharDriverState *serial_hds[MAX_SERIAL_PORTS];
bellard0824d6f2003-06-24 13:42:40 +0000135
136/***********************************************************/
bellard26aa7d72004-04-28 22:26:05 +0000137/* x86 ISA bus support */
138
139target_phys_addr_t isa_mem_base = 0;
bellard0824d6f2003-06-24 13:42:40 +0000140
bellardc4b1fcc2004-03-14 21:44:30 +0000141uint32_t default_ioport_readb(void *opaque, uint32_t address)
bellard0824d6f2003-06-24 13:42:40 +0000142{
143#ifdef DEBUG_UNUSED_IOPORT
144 fprintf(stderr, "inb: port=0x%04x\n", address);
145#endif
bellardfc01f7e2003-06-30 10:03:06 +0000146 return 0xff;
bellard0824d6f2003-06-24 13:42:40 +0000147}
148
bellardc4b1fcc2004-03-14 21:44:30 +0000149void default_ioport_writeb(void *opaque, uint32_t address, uint32_t data)
bellard0824d6f2003-06-24 13:42:40 +0000150{
151#ifdef DEBUG_UNUSED_IOPORT
152 fprintf(stderr, "outb: port=0x%04x data=0x%02x\n", address, data);
153#endif
154}
155
156/* default is to make two byte accesses */
bellardc4b1fcc2004-03-14 21:44:30 +0000157uint32_t default_ioport_readw(void *opaque, uint32_t address)
bellard0824d6f2003-06-24 13:42:40 +0000158{
159 uint32_t data;
bellarddb45c292004-05-12 19:50:26 +0000160 data = ioport_read_table[0][address](ioport_opaque[address], address);
161 address = (address + 1) & (MAX_IOPORTS - 1);
162 data |= ioport_read_table[0][address](ioport_opaque[address], address) << 8;
bellard0824d6f2003-06-24 13:42:40 +0000163 return data;
164}
165
bellardc4b1fcc2004-03-14 21:44:30 +0000166void default_ioport_writew(void *opaque, uint32_t address, uint32_t data)
bellard0824d6f2003-06-24 13:42:40 +0000167{
bellarddb45c292004-05-12 19:50:26 +0000168 ioport_write_table[0][address](ioport_opaque[address], address, data & 0xff);
169 address = (address + 1) & (MAX_IOPORTS - 1);
170 ioport_write_table[0][address](ioport_opaque[address], address, (data >> 8) & 0xff);
bellardfc01f7e2003-06-30 10:03:06 +0000171}
172
bellardc4b1fcc2004-03-14 21:44:30 +0000173uint32_t default_ioport_readl(void *opaque, uint32_t address)
bellardfc01f7e2003-06-30 10:03:06 +0000174{
175#ifdef DEBUG_UNUSED_IOPORT
176 fprintf(stderr, "inl: port=0x%04x\n", address);
177#endif
178 return 0xffffffff;
179}
180
bellardc4b1fcc2004-03-14 21:44:30 +0000181void default_ioport_writel(void *opaque, uint32_t address, uint32_t data)
bellardfc01f7e2003-06-30 10:03:06 +0000182{
183#ifdef DEBUG_UNUSED_IOPORT
184 fprintf(stderr, "outl: port=0x%04x data=0x%02x\n", address, data);
185#endif
bellard0824d6f2003-06-24 13:42:40 +0000186}
187
188void init_ioports(void)
189{
190 int i;
191
192 for(i = 0; i < MAX_IOPORTS; i++) {
bellardfc01f7e2003-06-30 10:03:06 +0000193 ioport_read_table[0][i] = default_ioport_readb;
194 ioport_write_table[0][i] = default_ioport_writeb;
195 ioport_read_table[1][i] = default_ioport_readw;
196 ioport_write_table[1][i] = default_ioport_writew;
197 ioport_read_table[2][i] = default_ioport_readl;
198 ioport_write_table[2][i] = default_ioport_writel;
bellard0824d6f2003-06-24 13:42:40 +0000199 }
200}
201
bellardfc01f7e2003-06-30 10:03:06 +0000202/* size is the word size in byte */
bellardc4b1fcc2004-03-14 21:44:30 +0000203int register_ioport_read(int start, int length, int size,
204 IOPortReadFunc *func, void *opaque)
bellard0824d6f2003-06-24 13:42:40 +0000205{
bellardfc01f7e2003-06-30 10:03:06 +0000206 int i, bsize;
bellard0824d6f2003-06-24 13:42:40 +0000207
bellardc4b1fcc2004-03-14 21:44:30 +0000208 if (size == 1) {
bellardfc01f7e2003-06-30 10:03:06 +0000209 bsize = 0;
bellardc4b1fcc2004-03-14 21:44:30 +0000210 } else if (size == 2) {
bellardfc01f7e2003-06-30 10:03:06 +0000211 bsize = 1;
bellardc4b1fcc2004-03-14 21:44:30 +0000212 } else if (size == 4) {
bellardfc01f7e2003-06-30 10:03:06 +0000213 bsize = 2;
bellardc4b1fcc2004-03-14 21:44:30 +0000214 } else {
215 hw_error("register_ioport_read: invalid size");
bellardfc01f7e2003-06-30 10:03:06 +0000216 return -1;
bellardc4b1fcc2004-03-14 21:44:30 +0000217 }
218 for(i = start; i < start + length; i += size) {
bellardfc01f7e2003-06-30 10:03:06 +0000219 ioport_read_table[bsize][i] = func;
bellardc4b1fcc2004-03-14 21:44:30 +0000220 if (ioport_opaque[i] != NULL && ioport_opaque[i] != opaque)
221 hw_error("register_ioport_read: invalid opaque");
222 ioport_opaque[i] = opaque;
223 }
bellard0824d6f2003-06-24 13:42:40 +0000224 return 0;
225}
226
bellardfc01f7e2003-06-30 10:03:06 +0000227/* size is the word size in byte */
bellardc4b1fcc2004-03-14 21:44:30 +0000228int register_ioport_write(int start, int length, int size,
229 IOPortWriteFunc *func, void *opaque)
bellard0824d6f2003-06-24 13:42:40 +0000230{
bellardfc01f7e2003-06-30 10:03:06 +0000231 int i, bsize;
bellard0824d6f2003-06-24 13:42:40 +0000232
bellardc4b1fcc2004-03-14 21:44:30 +0000233 if (size == 1) {
bellardfc01f7e2003-06-30 10:03:06 +0000234 bsize = 0;
bellardc4b1fcc2004-03-14 21:44:30 +0000235 } else if (size == 2) {
bellardfc01f7e2003-06-30 10:03:06 +0000236 bsize = 1;
bellardc4b1fcc2004-03-14 21:44:30 +0000237 } else if (size == 4) {
bellardfc01f7e2003-06-30 10:03:06 +0000238 bsize = 2;
bellardc4b1fcc2004-03-14 21:44:30 +0000239 } else {
240 hw_error("register_ioport_write: invalid size");
bellardfc01f7e2003-06-30 10:03:06 +0000241 return -1;
bellardc4b1fcc2004-03-14 21:44:30 +0000242 }
243 for(i = start; i < start + length; i += size) {
bellardfc01f7e2003-06-30 10:03:06 +0000244 ioport_write_table[bsize][i] = func;
bellardc4b1fcc2004-03-14 21:44:30 +0000245 if (ioport_opaque[i] != NULL && ioport_opaque[i] != opaque)
246 hw_error("register_ioport_read: invalid opaque");
247 ioport_opaque[i] = opaque;
248 }
bellardf1510b22003-06-25 00:07:40 +0000249 return 0;
250}
251
bellard69b91032004-05-18 23:05:28 +0000252void isa_unassign_ioport(int start, int length)
253{
254 int i;
255
256 for(i = start; i < start + length; i++) {
257 ioport_read_table[0][i] = default_ioport_readb;
258 ioport_read_table[1][i] = default_ioport_readw;
259 ioport_read_table[2][i] = default_ioport_readl;
260
261 ioport_write_table[0][i] = default_ioport_writeb;
262 ioport_write_table[1][i] = default_ioport_writew;
263 ioport_write_table[2][i] = default_ioport_writel;
264 }
265}
266
bellard0824d6f2003-06-24 13:42:40 +0000267void pstrcpy(char *buf, int buf_size, const char *str)
268{
269 int c;
270 char *q = buf;
271
272 if (buf_size <= 0)
273 return;
274
275 for(;;) {
276 c = *str++;
277 if (c == 0 || q >= buf + buf_size - 1)
278 break;
279 *q++ = c;
280 }
281 *q = '\0';
282}
283
284/* strcat and truncate. */
285char *pstrcat(char *buf, int buf_size, const char *s)
286{
287 int len;
288 len = strlen(buf);
289 if (len < buf_size)
290 pstrcpy(buf + len, buf_size - len, s);
291 return buf;
292}
293
bellard82c643f2004-07-14 17:28:13 +0000294int strstart(const char *str, const char *val, const char **ptr)
295{
296 const char *p, *q;
297 p = str;
298 q = val;
299 while (*q != '\0') {
300 if (*p != *q)
301 return 0;
302 p++;
303 q++;
304 }
305 if (ptr)
306 *ptr = p;
307 return 1;
308}
309
bellard0824d6f2003-06-24 13:42:40 +0000310/* return the size or -1 if error */
bellard7587cf42004-06-20 13:43:27 +0000311int get_image_size(const char *filename)
312{
313 int fd, size;
314 fd = open(filename, O_RDONLY | O_BINARY);
315 if (fd < 0)
316 return -1;
317 size = lseek(fd, 0, SEEK_END);
318 close(fd);
319 return size;
320}
321
322/* return the size or -1 if error */
bellard0824d6f2003-06-24 13:42:40 +0000323int load_image(const char *filename, uint8_t *addr)
324{
325 int fd, size;
bellard40c3bac2004-04-04 12:56:28 +0000326 fd = open(filename, O_RDONLY | O_BINARY);
bellard0824d6f2003-06-24 13:42:40 +0000327 if (fd < 0)
328 return -1;
329 size = lseek(fd, 0, SEEK_END);
330 lseek(fd, 0, SEEK_SET);
331 if (read(fd, addr, size) != size) {
332 close(fd);
333 return -1;
334 }
335 close(fd);
336 return size;
337}
338
bellardc45886d2004-01-05 00:02:06 +0000339void cpu_outb(CPUState *env, int addr, int val)
bellard0824d6f2003-06-24 13:42:40 +0000340{
bellardfd872592004-05-12 19:11:15 +0000341#ifdef DEBUG_IOPORT
342 if (loglevel & CPU_LOG_IOPORT)
343 fprintf(logfile, "outb: %04x %02x\n", addr, val);
344#endif
bellardc4b1fcc2004-03-14 21:44:30 +0000345 ioport_write_table[0][addr](ioport_opaque[addr], addr, val);
bellard0824d6f2003-06-24 13:42:40 +0000346}
347
bellardc45886d2004-01-05 00:02:06 +0000348void cpu_outw(CPUState *env, int addr, int val)
bellard0824d6f2003-06-24 13:42:40 +0000349{
bellardfd872592004-05-12 19:11:15 +0000350#ifdef DEBUG_IOPORT
351 if (loglevel & CPU_LOG_IOPORT)
352 fprintf(logfile, "outw: %04x %04x\n", addr, val);
353#endif
bellardc4b1fcc2004-03-14 21:44:30 +0000354 ioport_write_table[1][addr](ioport_opaque[addr], addr, val);
bellard0824d6f2003-06-24 13:42:40 +0000355}
356
bellardc45886d2004-01-05 00:02:06 +0000357void cpu_outl(CPUState *env, int addr, int val)
bellard0824d6f2003-06-24 13:42:40 +0000358{
bellardfd872592004-05-12 19:11:15 +0000359#ifdef DEBUG_IOPORT
360 if (loglevel & CPU_LOG_IOPORT)
361 fprintf(logfile, "outl: %04x %08x\n", addr, val);
362#endif
bellardc4b1fcc2004-03-14 21:44:30 +0000363 ioport_write_table[2][addr](ioport_opaque[addr], addr, val);
bellard0824d6f2003-06-24 13:42:40 +0000364}
365
bellardc45886d2004-01-05 00:02:06 +0000366int cpu_inb(CPUState *env, int addr)
bellard0824d6f2003-06-24 13:42:40 +0000367{
bellardfd872592004-05-12 19:11:15 +0000368 int val;
bellardfd872592004-05-12 19:11:15 +0000369 val = ioport_read_table[0][addr](ioport_opaque[addr], addr);
370#ifdef DEBUG_IOPORT
371 if (loglevel & CPU_LOG_IOPORT)
372 fprintf(logfile, "inb : %04x %02x\n", addr, val);
373#endif
374 return val;
bellard0824d6f2003-06-24 13:42:40 +0000375}
376
bellardc45886d2004-01-05 00:02:06 +0000377int cpu_inw(CPUState *env, int addr)
bellard0824d6f2003-06-24 13:42:40 +0000378{
bellardfd872592004-05-12 19:11:15 +0000379 int val;
bellardfd872592004-05-12 19:11:15 +0000380 val = ioport_read_table[1][addr](ioport_opaque[addr], addr);
381#ifdef DEBUG_IOPORT
382 if (loglevel & CPU_LOG_IOPORT)
383 fprintf(logfile, "inw : %04x %04x\n", addr, val);
384#endif
385 return val;
bellard0824d6f2003-06-24 13:42:40 +0000386}
387
bellardc45886d2004-01-05 00:02:06 +0000388int cpu_inl(CPUState *env, int addr)
bellard0824d6f2003-06-24 13:42:40 +0000389{
bellardfd872592004-05-12 19:11:15 +0000390 int val;
bellardfd872592004-05-12 19:11:15 +0000391 val = ioport_read_table[2][addr](ioport_opaque[addr], addr);
392#ifdef DEBUG_IOPORT
393 if (loglevel & CPU_LOG_IOPORT)
394 fprintf(logfile, "inl : %04x %08x\n", addr, val);
395#endif
396 return val;
bellard0824d6f2003-06-24 13:42:40 +0000397}
398
399/***********************************************************/
bellard0824d6f2003-06-24 13:42:40 +0000400void hw_error(const char *fmt, ...)
401{
402 va_list ap;
403
404 va_start(ap, fmt);
405 fprintf(stderr, "qemu: hardware error: ");
406 vfprintf(stderr, fmt, ap);
407 fprintf(stderr, "\n");
408#ifdef TARGET_I386
bellard7fe48482004-10-09 18:08:01 +0000409 cpu_dump_state(global_env, stderr, fprintf, X86_DUMP_FPU | X86_DUMP_CCOP);
bellardc45886d2004-01-05 00:02:06 +0000410#else
bellard7fe48482004-10-09 18:08:01 +0000411 cpu_dump_state(global_env, stderr, fprintf, 0);
bellard0824d6f2003-06-24 13:42:40 +0000412#endif
413 va_end(ap);
414 abort();
415}
416
bellard8a7ddc32004-03-31 19:00:16 +0000417/***********************************************************/
bellard63066f42004-06-03 18:45:02 +0000418/* keyboard/mouse */
419
420static QEMUPutKBDEvent *qemu_put_kbd_event;
421static void *qemu_put_kbd_event_opaque;
422static QEMUPutMouseEvent *qemu_put_mouse_event;
423static void *qemu_put_mouse_event_opaque;
424
425void qemu_add_kbd_event_handler(QEMUPutKBDEvent *func, void *opaque)
426{
427 qemu_put_kbd_event_opaque = opaque;
428 qemu_put_kbd_event = func;
429}
430
431void qemu_add_mouse_event_handler(QEMUPutMouseEvent *func, void *opaque)
432{
433 qemu_put_mouse_event_opaque = opaque;
434 qemu_put_mouse_event = func;
435}
436
437void kbd_put_keycode(int keycode)
438{
439 if (qemu_put_kbd_event) {
440 qemu_put_kbd_event(qemu_put_kbd_event_opaque, keycode);
441 }
442}
443
444void kbd_mouse_event(int dx, int dy, int dz, int buttons_state)
445{
446 if (qemu_put_mouse_event) {
447 qemu_put_mouse_event(qemu_put_mouse_event_opaque,
448 dx, dy, dz, buttons_state);
449 }
450}
451
452/***********************************************************/
bellard8a7ddc32004-03-31 19:00:16 +0000453/* timers */
454
bellard34865132003-10-05 14:28:56 +0000455#if defined(__powerpc__)
456
457static inline uint32_t get_tbl(void)
458{
459 uint32_t tbl;
460 asm volatile("mftb %0" : "=r" (tbl));
461 return tbl;
462}
463
464static inline uint32_t get_tbu(void)
465{
466 uint32_t tbl;
467 asm volatile("mftbu %0" : "=r" (tbl));
468 return tbl;
469}
470
471int64_t cpu_get_real_ticks(void)
472{
473 uint32_t l, h, h1;
474 /* NOTE: we test if wrapping has occurred */
475 do {
476 h = get_tbu();
477 l = get_tbl();
478 h1 = get_tbu();
479 } while (h != h1);
480 return ((int64_t)h << 32) | l;
481}
482
483#elif defined(__i386__)
484
485int64_t cpu_get_real_ticks(void)
486{
487 int64_t val;
bellarde463b582004-04-02 20:57:58 +0000488 asm volatile ("rdtsc" : "=A" (val));
bellard34865132003-10-05 14:28:56 +0000489 return val;
490}
491
bellard1115dde2004-04-25 18:57:49 +0000492#elif defined(__x86_64__)
493
494int64_t cpu_get_real_ticks(void)
495{
496 uint32_t low,high;
497 int64_t val;
498 asm volatile("rdtsc" : "=a" (low), "=d" (high));
499 val = high;
500 val <<= 32;
501 val |= low;
502 return val;
503}
504
bellard34865132003-10-05 14:28:56 +0000505#else
506#error unsupported CPU
507#endif
508
509static int64_t cpu_ticks_offset;
bellard8a7ddc32004-03-31 19:00:16 +0000510static int cpu_ticks_enabled;
bellard34865132003-10-05 14:28:56 +0000511
bellard8a7ddc32004-03-31 19:00:16 +0000512static inline int64_t cpu_get_ticks(void)
bellard34865132003-10-05 14:28:56 +0000513{
bellard8a7ddc32004-03-31 19:00:16 +0000514 if (!cpu_ticks_enabled) {
515 return cpu_ticks_offset;
516 } else {
517 return cpu_get_real_ticks() + cpu_ticks_offset;
518 }
bellard34865132003-10-05 14:28:56 +0000519}
520
521/* enable cpu_get_ticks() */
522void cpu_enable_ticks(void)
523{
bellard8a7ddc32004-03-31 19:00:16 +0000524 if (!cpu_ticks_enabled) {
525 cpu_ticks_offset -= cpu_get_real_ticks();
526 cpu_ticks_enabled = 1;
527 }
bellard34865132003-10-05 14:28:56 +0000528}
529
530/* disable cpu_get_ticks() : the clock is stopped. You must not call
531 cpu_get_ticks() after that. */
532void cpu_disable_ticks(void)
533{
bellard8a7ddc32004-03-31 19:00:16 +0000534 if (cpu_ticks_enabled) {
535 cpu_ticks_offset = cpu_get_ticks();
536 cpu_ticks_enabled = 0;
537 }
bellard34865132003-10-05 14:28:56 +0000538}
539
bellard67b915a2004-03-31 23:37:16 +0000540static int64_t get_clock(void)
bellard0824d6f2003-06-24 13:42:40 +0000541{
bellard67b915a2004-03-31 23:37:16 +0000542#ifdef _WIN32
543 struct _timeb tb;
544 _ftime(&tb);
545 return ((int64_t)tb.time * 1000 + (int64_t)tb.millitm) * 1000;
546#else
bellard0824d6f2003-06-24 13:42:40 +0000547 struct timeval tv;
548 gettimeofday(&tv, NULL);
549 return tv.tv_sec * 1000000LL + tv.tv_usec;
bellard67b915a2004-03-31 23:37:16 +0000550#endif
bellard0824d6f2003-06-24 13:42:40 +0000551}
552
bellard0824d6f2003-06-24 13:42:40 +0000553void cpu_calibrate_ticks(void)
554{
555 int64_t usec, ticks;
556
557 usec = get_clock();
bellard8a7ddc32004-03-31 19:00:16 +0000558 ticks = cpu_get_real_ticks();
bellard67b915a2004-03-31 23:37:16 +0000559#ifdef _WIN32
560 Sleep(50);
561#else
bellard0824d6f2003-06-24 13:42:40 +0000562 usleep(50 * 1000);
bellard67b915a2004-03-31 23:37:16 +0000563#endif
bellard0824d6f2003-06-24 13:42:40 +0000564 usec = get_clock() - usec;
bellard8a7ddc32004-03-31 19:00:16 +0000565 ticks = cpu_get_real_ticks() - ticks;
bellard0824d6f2003-06-24 13:42:40 +0000566 ticks_per_sec = (ticks * 1000000LL + (usec >> 1)) / usec;
567}
568
bellard87858c82003-06-27 12:01:39 +0000569/* compute with 96 bit intermediate result: (a*b)/c */
bellard80cabfa2004-03-14 12:20:30 +0000570uint64_t muldiv64(uint64_t a, uint32_t b, uint32_t c)
bellard87858c82003-06-27 12:01:39 +0000571{
572 union {
573 uint64_t ll;
574 struct {
575#ifdef WORDS_BIGENDIAN
576 uint32_t high, low;
577#else
578 uint32_t low, high;
579#endif
580 } l;
581 } u, res;
582 uint64_t rl, rh;
583
584 u.ll = a;
585 rl = (uint64_t)u.l.low * (uint64_t)b;
586 rh = (uint64_t)u.l.high * (uint64_t)b;
587 rh += (rl >> 32);
588 res.l.high = rh / c;
589 res.l.low = (((rh % c) << 32) + (rl & 0xffffffff)) / c;
590 return res.ll;
591}
592
bellard8a7ddc32004-03-31 19:00:16 +0000593#define QEMU_TIMER_REALTIME 0
594#define QEMU_TIMER_VIRTUAL 1
595
596struct QEMUClock {
597 int type;
598 /* XXX: add frequency */
599};
600
601struct QEMUTimer {
602 QEMUClock *clock;
603 int64_t expire_time;
604 QEMUTimerCB *cb;
605 void *opaque;
606 struct QEMUTimer *next;
607};
608
609QEMUClock *rt_clock;
610QEMUClock *vm_clock;
611
612static QEMUTimer *active_timers[2];
bellard40c3bac2004-04-04 12:56:28 +0000613#ifdef _WIN32
614static MMRESULT timerID;
615#else
bellard8a7ddc32004-03-31 19:00:16 +0000616/* frequency of the times() clock tick */
617static int timer_freq;
bellard67b915a2004-03-31 23:37:16 +0000618#endif
bellard8a7ddc32004-03-31 19:00:16 +0000619
620QEMUClock *qemu_new_clock(int type)
621{
622 QEMUClock *clock;
623 clock = qemu_mallocz(sizeof(QEMUClock));
624 if (!clock)
625 return NULL;
626 clock->type = type;
627 return clock;
628}
629
630QEMUTimer *qemu_new_timer(QEMUClock *clock, QEMUTimerCB *cb, void *opaque)
631{
632 QEMUTimer *ts;
633
634 ts = qemu_mallocz(sizeof(QEMUTimer));
635 ts->clock = clock;
636 ts->cb = cb;
637 ts->opaque = opaque;
638 return ts;
639}
640
641void qemu_free_timer(QEMUTimer *ts)
642{
643 qemu_free(ts);
644}
645
646/* stop a timer, but do not dealloc it */
647void qemu_del_timer(QEMUTimer *ts)
648{
649 QEMUTimer **pt, *t;
650
651 /* NOTE: this code must be signal safe because
652 qemu_timer_expired() can be called from a signal. */
653 pt = &active_timers[ts->clock->type];
654 for(;;) {
655 t = *pt;
656 if (!t)
657 break;
658 if (t == ts) {
659 *pt = t->next;
660 break;
661 }
662 pt = &t->next;
663 }
664}
665
666/* modify the current timer so that it will be fired when current_time
667 >= expire_time. The corresponding callback will be called. */
668void qemu_mod_timer(QEMUTimer *ts, int64_t expire_time)
669{
670 QEMUTimer **pt, *t;
671
672 qemu_del_timer(ts);
673
674 /* add the timer in the sorted list */
675 /* NOTE: this code must be signal safe because
676 qemu_timer_expired() can be called from a signal. */
677 pt = &active_timers[ts->clock->type];
678 for(;;) {
679 t = *pt;
680 if (!t)
681 break;
682 if (t->expire_time > expire_time)
683 break;
684 pt = &t->next;
685 }
686 ts->expire_time = expire_time;
687 ts->next = *pt;
688 *pt = ts;
689}
690
691int qemu_timer_pending(QEMUTimer *ts)
692{
693 QEMUTimer *t;
694 for(t = active_timers[ts->clock->type]; t != NULL; t = t->next) {
695 if (t == ts)
696 return 1;
697 }
698 return 0;
699}
700
701static inline int qemu_timer_expired(QEMUTimer *timer_head, int64_t current_time)
702{
703 if (!timer_head)
704 return 0;
705 return (timer_head->expire_time <= current_time);
706}
707
708static void qemu_run_timers(QEMUTimer **ptimer_head, int64_t current_time)
709{
710 QEMUTimer *ts;
711
712 for(;;) {
713 ts = *ptimer_head;
bellarde95c8d52004-09-30 22:22:08 +0000714 if (!ts || ts->expire_time > current_time)
bellard8a7ddc32004-03-31 19:00:16 +0000715 break;
716 /* remove timer from the list before calling the callback */
717 *ptimer_head = ts->next;
718 ts->next = NULL;
719
720 /* run the callback (the timer list can be modified) */
721 ts->cb(ts->opaque);
722 }
723}
724
725int64_t qemu_get_clock(QEMUClock *clock)
726{
727 switch(clock->type) {
728 case QEMU_TIMER_REALTIME:
bellard67b915a2004-03-31 23:37:16 +0000729#ifdef _WIN32
730 return GetTickCount();
731#else
bellard7d3505c2004-05-12 19:32:15 +0000732 {
733 struct tms tp;
734
735 /* Note that using gettimeofday() is not a good solution
736 for timers because its value change when the date is
737 modified. */
738 if (timer_freq == 100) {
739 return times(&tp) * 10;
740 } else {
741 return ((int64_t)times(&tp) * 1000) / timer_freq;
742 }
bellard8a7ddc32004-03-31 19:00:16 +0000743 }
bellard67b915a2004-03-31 23:37:16 +0000744#endif
bellard8a7ddc32004-03-31 19:00:16 +0000745 default:
746 case QEMU_TIMER_VIRTUAL:
747 return cpu_get_ticks();
748 }
749}
750
751/* save a timer */
752void qemu_put_timer(QEMUFile *f, QEMUTimer *ts)
753{
754 uint64_t expire_time;
755
756 if (qemu_timer_pending(ts)) {
757 expire_time = ts->expire_time;
758 } else {
759 expire_time = -1;
760 }
761 qemu_put_be64(f, expire_time);
762}
763
764void qemu_get_timer(QEMUFile *f, QEMUTimer *ts)
765{
766 uint64_t expire_time;
767
768 expire_time = qemu_get_be64(f);
769 if (expire_time != -1) {
770 qemu_mod_timer(ts, expire_time);
771 } else {
772 qemu_del_timer(ts);
773 }
774}
775
776static void timer_save(QEMUFile *f, void *opaque)
777{
778 if (cpu_ticks_enabled) {
779 hw_error("cannot save state if virtual timers are running");
780 }
781 qemu_put_be64s(f, &cpu_ticks_offset);
782 qemu_put_be64s(f, &ticks_per_sec);
783}
784
785static int timer_load(QEMUFile *f, void *opaque, int version_id)
786{
787 if (version_id != 1)
788 return -EINVAL;
789 if (cpu_ticks_enabled) {
790 return -EINVAL;
791 }
792 qemu_get_be64s(f, &cpu_ticks_offset);
793 qemu_get_be64s(f, &ticks_per_sec);
794 return 0;
795}
796
bellard67b915a2004-03-31 23:37:16 +0000797#ifdef _WIN32
798void CALLBACK host_alarm_handler(UINT uTimerID, UINT uMsg,
799 DWORD_PTR dwUser, DWORD_PTR dw1, DWORD_PTR dw2)
800#else
bellard8a7ddc32004-03-31 19:00:16 +0000801static void host_alarm_handler(int host_signum)
bellard67b915a2004-03-31 23:37:16 +0000802#endif
bellard8a7ddc32004-03-31 19:00:16 +0000803{
bellard02ba45c2004-06-25 14:46:23 +0000804#if 0
805#define DISP_FREQ 1000
806 {
807 static int64_t delta_min = INT64_MAX;
808 static int64_t delta_max, delta_cum, last_clock, delta, ti;
809 static int count;
810 ti = qemu_get_clock(vm_clock);
811 if (last_clock != 0) {
812 delta = ti - last_clock;
813 if (delta < delta_min)
814 delta_min = delta;
815 if (delta > delta_max)
816 delta_max = delta;
817 delta_cum += delta;
818 if (++count == DISP_FREQ) {
819 printf("timer: min=%lld us max=%lld us avg=%lld us avg_freq=%0.3f Hz\n",
820 muldiv64(delta_min, 1000000, ticks_per_sec),
821 muldiv64(delta_max, 1000000, ticks_per_sec),
822 muldiv64(delta_cum, 1000000 / DISP_FREQ, ticks_per_sec),
823 (double)ticks_per_sec / ((double)delta_cum / DISP_FREQ));
824 count = 0;
825 delta_min = INT64_MAX;
826 delta_max = 0;
827 delta_cum = 0;
828 }
829 }
830 last_clock = ti;
831 }
832#endif
bellard8a7ddc32004-03-31 19:00:16 +0000833 if (qemu_timer_expired(active_timers[QEMU_TIMER_VIRTUAL],
834 qemu_get_clock(vm_clock)) ||
835 qemu_timer_expired(active_timers[QEMU_TIMER_REALTIME],
836 qemu_get_clock(rt_clock))) {
837 /* stop the cpu because a timer occured */
838 cpu_interrupt(global_env, CPU_INTERRUPT_EXIT);
839 }
840}
841
bellardfd872592004-05-12 19:11:15 +0000842#ifndef _WIN32
843
bellard829309c2004-05-20 13:20:12 +0000844#if defined(__linux__)
845
bellardfd872592004-05-12 19:11:15 +0000846#define RTC_FREQ 1024
847
848static int rtc_fd;
bellard829309c2004-05-20 13:20:12 +0000849
bellardfd872592004-05-12 19:11:15 +0000850static int start_rtc_timer(void)
851{
852 rtc_fd = open("/dev/rtc", O_RDONLY);
853 if (rtc_fd < 0)
854 return -1;
855 if (ioctl(rtc_fd, RTC_IRQP_SET, RTC_FREQ) < 0) {
856 fprintf(stderr, "Could not configure '/dev/rtc' to have a 1024 Hz timer. This is not a fatal\n"
857 "error, but for better emulation accuracy either use a 2.6 host Linux kernel or\n"
858 "type 'echo 1024 > /proc/sys/dev/rtc/max-user-freq' as root.\n");
859 goto fail;
860 }
861 if (ioctl(rtc_fd, RTC_PIE_ON, 0) < 0) {
862 fail:
863 close(rtc_fd);
864 return -1;
865 }
866 pit_min_timer_count = PIT_FREQ / RTC_FREQ;
867 return 0;
868}
869
bellard829309c2004-05-20 13:20:12 +0000870#else
871
872static int start_rtc_timer(void)
873{
874 return -1;
875}
876
877#endif /* !defined(__linux__) */
878
879#endif /* !defined(_WIN32) */
bellardfd872592004-05-12 19:11:15 +0000880
bellard8a7ddc32004-03-31 19:00:16 +0000881static void init_timers(void)
882{
bellard8a7ddc32004-03-31 19:00:16 +0000883 rt_clock = qemu_new_clock(QEMU_TIMER_REALTIME);
884 vm_clock = qemu_new_clock(QEMU_TIMER_VIRTUAL);
885
bellard67b915a2004-03-31 23:37:16 +0000886#ifdef _WIN32
887 {
888 int count=0;
bellard40c3bac2004-04-04 12:56:28 +0000889 timerID = timeSetEvent(10, // interval (ms)
890 0, // resolution
891 host_alarm_handler, // function
892 (DWORD)&count, // user parameter
893 TIME_PERIODIC | TIME_CALLBACK_FUNCTION);
bellard67b915a2004-03-31 23:37:16 +0000894 if( !timerID ) {
895 perror("failed timer alarm");
896 exit(1);
897 }
898 }
899 pit_min_timer_count = ((uint64_t)10000 * PIT_FREQ) / 1000000;
900#else
901 {
902 struct sigaction act;
903 struct itimerval itv;
904
905 /* get times() syscall frequency */
906 timer_freq = sysconf(_SC_CLK_TCK);
907
908 /* timer signal */
909 sigfillset(&act.sa_mask);
910 act.sa_flags = 0;
bellard8a7ddc32004-03-31 19:00:16 +0000911#if defined (TARGET_I386) && defined(USE_CODE_COPY)
bellard67b915a2004-03-31 23:37:16 +0000912 act.sa_flags |= SA_ONSTACK;
bellard8a7ddc32004-03-31 19:00:16 +0000913#endif
bellard67b915a2004-03-31 23:37:16 +0000914 act.sa_handler = host_alarm_handler;
915 sigaction(SIGALRM, &act, NULL);
bellardfd872592004-05-12 19:11:15 +0000916
bellard67b915a2004-03-31 23:37:16 +0000917 itv.it_interval.tv_sec = 0;
918 itv.it_interval.tv_usec = 1000;
919 itv.it_value.tv_sec = 0;
920 itv.it_value.tv_usec = 10 * 1000;
921 setitimer(ITIMER_REAL, &itv, NULL);
922 /* we probe the tick duration of the kernel to inform the user if
923 the emulated kernel requested a too high timer frequency */
924 getitimer(ITIMER_REAL, &itv);
bellardfd872592004-05-12 19:11:15 +0000925
bellard83fb7ad2004-07-05 21:25:26 +0000926#if defined(__linux__)
bellardfd872592004-05-12 19:11:15 +0000927 if (itv.it_interval.tv_usec > 1000) {
928 /* try to use /dev/rtc to have a faster timer */
929 if (start_rtc_timer() < 0)
930 goto use_itimer;
931 /* disable itimer */
932 itv.it_interval.tv_sec = 0;
933 itv.it_interval.tv_usec = 0;
934 itv.it_value.tv_sec = 0;
935 itv.it_value.tv_usec = 0;
936 setitimer(ITIMER_REAL, &itv, NULL);
937
938 /* use the RTC */
bellarda1968d72004-06-25 17:06:27 +0000939 sigaction(SIGIO, &act, NULL);
bellardfd872592004-05-12 19:11:15 +0000940 fcntl(rtc_fd, F_SETFL, O_ASYNC);
941 fcntl(rtc_fd, F_SETOWN, getpid());
bellard83fb7ad2004-07-05 21:25:26 +0000942 } else
943#endif /* defined(__linux__) */
944 {
bellardfd872592004-05-12 19:11:15 +0000945 use_itimer:
946 pit_min_timer_count = ((uint64_t)itv.it_interval.tv_usec *
947 PIT_FREQ) / 1000000;
948 }
bellard67b915a2004-03-31 23:37:16 +0000949 }
950#endif
bellard8a7ddc32004-03-31 19:00:16 +0000951}
952
bellard40c3bac2004-04-04 12:56:28 +0000953void quit_timers(void)
954{
955#ifdef _WIN32
956 timeKillEvent(timerID);
957#endif
958}
959
bellardc4b1fcc2004-03-14 21:44:30 +0000960/***********************************************************/
bellard82c643f2004-07-14 17:28:13 +0000961/* character device */
bellardc45886d2004-01-05 00:02:06 +0000962
bellard82c643f2004-07-14 17:28:13 +0000963int qemu_chr_write(CharDriverState *s, const uint8_t *buf, int len)
bellard67b915a2004-03-31 23:37:16 +0000964{
bellard82c643f2004-07-14 17:28:13 +0000965 return s->chr_write(s, buf, len);
bellard67b915a2004-03-31 23:37:16 +0000966}
967
bellard82c643f2004-07-14 17:28:13 +0000968void qemu_chr_printf(CharDriverState *s, const char *fmt, ...)
bellard0824d6f2003-06-24 13:42:40 +0000969{
bellard82c643f2004-07-14 17:28:13 +0000970 char buf[4096];
971 va_list ap;
972 va_start(ap, fmt);
973 vsnprintf(buf, sizeof(buf), fmt, ap);
974 qemu_chr_write(s, buf, strlen(buf));
975 va_end(ap);
976}
977
bellard5905b2e2004-08-01 21:53:26 +0000978void qemu_chr_send_event(CharDriverState *s, int event)
979{
980 if (s->chr_send_event)
981 s->chr_send_event(s, event);
982}
983
bellard82c643f2004-07-14 17:28:13 +0000984void qemu_chr_add_read_handler(CharDriverState *s,
985 IOCanRWHandler *fd_can_read,
986 IOReadHandler *fd_read, void *opaque)
987{
988 s->chr_add_read_handler(s, fd_can_read, fd_read, opaque);
989}
990
991void qemu_chr_add_event_handler(CharDriverState *s, IOEventHandler *chr_event)
992{
993 s->chr_event = chr_event;
994}
995
996static int null_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
997{
998 return len;
999}
1000
1001static void null_chr_add_read_handler(CharDriverState *chr,
1002 IOCanRWHandler *fd_can_read,
1003 IOReadHandler *fd_read, void *opaque)
1004{
1005}
1006
1007CharDriverState *qemu_chr_open_null(void)
1008{
1009 CharDriverState *chr;
1010
1011 chr = qemu_mallocz(sizeof(CharDriverState));
1012 if (!chr)
1013 return NULL;
1014 chr->chr_write = null_chr_write;
1015 chr->chr_add_read_handler = null_chr_add_read_handler;
1016 return chr;
1017}
1018
1019#ifndef _WIN32
1020
1021typedef struct {
1022 int fd_in, fd_out;
1023 /* for nographic stdio only */
1024 IOCanRWHandler *fd_can_read;
1025 IOReadHandler *fd_read;
1026 void *fd_opaque;
1027} FDCharDriver;
1028
1029#define STDIO_MAX_CLIENTS 2
1030
1031static int stdio_nb_clients;
1032static CharDriverState *stdio_clients[STDIO_MAX_CLIENTS];
1033
bellard1d969052004-09-18 19:34:39 +00001034static int unix_write(int fd, const uint8_t *buf, int len1)
1035{
1036 int ret, len;
1037
1038 len = len1;
1039 while (len > 0) {
1040 ret = write(fd, buf, len);
1041 if (ret < 0) {
1042 if (errno != EINTR && errno != EAGAIN)
1043 return -1;
1044 } else if (ret == 0) {
1045 break;
1046 } else {
1047 buf += ret;
1048 len -= ret;
1049 }
1050 }
1051 return len1 - len;
1052}
1053
bellard82c643f2004-07-14 17:28:13 +00001054static int fd_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
1055{
1056 FDCharDriver *s = chr->opaque;
bellard1d969052004-09-18 19:34:39 +00001057 return unix_write(s->fd_out, buf, len);
bellard82c643f2004-07-14 17:28:13 +00001058}
1059
1060static void fd_chr_add_read_handler(CharDriverState *chr,
1061 IOCanRWHandler *fd_can_read,
1062 IOReadHandler *fd_read, void *opaque)
1063{
1064 FDCharDriver *s = chr->opaque;
1065
1066 if (nographic && s->fd_in == 0) {
1067 s->fd_can_read = fd_can_read;
1068 s->fd_read = fd_read;
1069 s->fd_opaque = opaque;
bellard0824d6f2003-06-24 13:42:40 +00001070 } else {
bellard82c643f2004-07-14 17:28:13 +00001071 qemu_add_fd_read_handler(s->fd_in, fd_can_read, fd_read, opaque);
bellard0824d6f2003-06-24 13:42:40 +00001072 }
1073}
1074
bellard82c643f2004-07-14 17:28:13 +00001075/* open a character device to a unix fd */
1076CharDriverState *qemu_chr_open_fd(int fd_in, int fd_out)
1077{
1078 CharDriverState *chr;
1079 FDCharDriver *s;
1080
1081 chr = qemu_mallocz(sizeof(CharDriverState));
1082 if (!chr)
1083 return NULL;
1084 s = qemu_mallocz(sizeof(FDCharDriver));
1085 if (!s) {
1086 free(chr);
1087 return NULL;
1088 }
1089 s->fd_in = fd_in;
1090 s->fd_out = fd_out;
1091 chr->opaque = s;
1092 chr->chr_write = fd_chr_write;
1093 chr->chr_add_read_handler = fd_chr_add_read_handler;
1094 return chr;
1095}
1096
1097/* for STDIO, we handle the case where several clients use it
1098 (nographic mode) */
1099
1100#define TERM_ESCAPE 0x01 /* ctrl-a is used for escape */
1101
1102static int term_got_escape, client_index;
1103
1104void term_print_help(void)
1105{
1106 printf("\n"
1107 "C-a h print this help\n"
1108 "C-a x exit emulator\n"
1109 "C-a s save disk data back to file (if -snapshot)\n"
1110 "C-a b send break (magic sysrq)\n"
1111 "C-a c switch between console and monitor\n"
1112 "C-a C-a send C-a\n"
1113 );
1114}
1115
1116/* called when a char is received */
1117static void stdio_received_byte(int ch)
1118{
1119 if (term_got_escape) {
1120 term_got_escape = 0;
1121 switch(ch) {
1122 case 'h':
1123 term_print_help();
1124 break;
1125 case 'x':
1126 exit(0);
1127 break;
1128 case 's':
1129 {
1130 int i;
1131 for (i = 0; i < MAX_DISKS; i++) {
1132 if (bs_table[i])
1133 bdrv_commit(bs_table[i]);
1134 }
1135 }
1136 break;
1137 case 'b':
1138 if (client_index < stdio_nb_clients) {
1139 CharDriverState *chr;
1140 FDCharDriver *s;
1141
1142 chr = stdio_clients[client_index];
1143 s = chr->opaque;
1144 chr->chr_event(s->fd_opaque, CHR_EVENT_BREAK);
1145 }
1146 break;
1147 case 'c':
1148 client_index++;
1149 if (client_index >= stdio_nb_clients)
1150 client_index = 0;
1151 if (client_index == 0) {
1152 /* send a new line in the monitor to get the prompt */
1153 ch = '\r';
1154 goto send_char;
1155 }
1156 break;
1157 case TERM_ESCAPE:
1158 goto send_char;
1159 }
1160 } else if (ch == TERM_ESCAPE) {
1161 term_got_escape = 1;
1162 } else {
1163 send_char:
1164 if (client_index < stdio_nb_clients) {
1165 uint8_t buf[1];
1166 CharDriverState *chr;
1167 FDCharDriver *s;
1168
1169 chr = stdio_clients[client_index];
1170 s = chr->opaque;
1171 buf[0] = ch;
1172 /* XXX: should queue the char if the device is not
1173 ready */
1174 if (s->fd_can_read(s->fd_opaque) > 0)
1175 s->fd_read(s->fd_opaque, buf, 1);
1176 }
1177 }
1178}
1179
1180static int stdio_can_read(void *opaque)
1181{
1182 /* XXX: not strictly correct */
1183 return 1;
1184}
1185
1186static void stdio_read(void *opaque, const uint8_t *buf, int size)
1187{
1188 int i;
1189 for(i = 0; i < size; i++)
1190 stdio_received_byte(buf[i]);
1191}
1192
bellard8d11df92004-08-24 21:13:40 +00001193/* init terminal so that we can grab keys */
1194static struct termios oldtty;
1195static int old_fd0_flags;
1196
1197static void term_exit(void)
1198{
1199 tcsetattr (0, TCSANOW, &oldtty);
1200 fcntl(0, F_SETFL, old_fd0_flags);
1201}
1202
1203static void term_init(void)
1204{
1205 struct termios tty;
1206
1207 tcgetattr (0, &tty);
1208 oldtty = tty;
1209 old_fd0_flags = fcntl(0, F_GETFL);
1210
1211 tty.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP
1212 |INLCR|IGNCR|ICRNL|IXON);
1213 tty.c_oflag |= OPOST;
1214 tty.c_lflag &= ~(ECHO|ECHONL|ICANON|IEXTEN);
1215 /* if graphical mode, we allow Ctrl-C handling */
1216 if (nographic)
1217 tty.c_lflag &= ~ISIG;
1218 tty.c_cflag &= ~(CSIZE|PARENB);
1219 tty.c_cflag |= CS8;
1220 tty.c_cc[VMIN] = 1;
1221 tty.c_cc[VTIME] = 0;
1222
1223 tcsetattr (0, TCSANOW, &tty);
1224
1225 atexit(term_exit);
1226
1227 fcntl(0, F_SETFL, O_NONBLOCK);
1228}
1229
bellard82c643f2004-07-14 17:28:13 +00001230CharDriverState *qemu_chr_open_stdio(void)
1231{
1232 CharDriverState *chr;
1233
1234 if (nographic) {
1235 if (stdio_nb_clients >= STDIO_MAX_CLIENTS)
1236 return NULL;
1237 chr = qemu_chr_open_fd(0, 1);
1238 if (stdio_nb_clients == 0)
1239 qemu_add_fd_read_handler(0, stdio_can_read, stdio_read, NULL);
1240 client_index = stdio_nb_clients;
1241 } else {
1242 if (stdio_nb_clients != 0)
1243 return NULL;
1244 chr = qemu_chr_open_fd(0, 1);
1245 }
1246 stdio_clients[stdio_nb_clients++] = chr;
bellard8d11df92004-08-24 21:13:40 +00001247 if (stdio_nb_clients == 1) {
1248 /* set the terminal in raw mode */
1249 term_init();
1250 }
bellard82c643f2004-07-14 17:28:13 +00001251 return chr;
1252}
1253
1254#if defined(__linux__)
1255CharDriverState *qemu_chr_open_pty(void)
1256{
1257 char slave_name[1024];
1258 int master_fd, slave_fd;
1259
1260 /* Not satisfying */
1261 if (openpty(&master_fd, &slave_fd, slave_name, NULL, NULL) < 0) {
1262 return NULL;
1263 }
1264 fprintf(stderr, "char device redirected to %s\n", slave_name);
1265 return qemu_chr_open_fd(master_fd, master_fd);
1266}
1267#else
1268CharDriverState *qemu_chr_open_pty(void)
1269{
1270 return NULL;
1271}
bellard67b915a2004-03-31 23:37:16 +00001272#endif
1273
bellard82c643f2004-07-14 17:28:13 +00001274#endif /* !defined(_WIN32) */
1275
1276CharDriverState *qemu_chr_open(const char *filename)
1277{
1278 if (!strcmp(filename, "vc")) {
1279 return text_console_init(&display_state);
1280 } else if (!strcmp(filename, "null")) {
1281 return qemu_chr_open_null();
1282 } else
1283#ifndef _WIN32
1284 if (!strcmp(filename, "pty")) {
1285 return qemu_chr_open_pty();
1286 } else if (!strcmp(filename, "stdio")) {
1287 return qemu_chr_open_stdio();
1288 } else
1289#endif
1290 {
1291 return NULL;
1292 }
1293}
1294
bellardf1510b22003-06-25 00:07:40 +00001295/***********************************************************/
bellardc20709a2004-04-21 23:27:19 +00001296/* Linux network device redirectors */
bellardf1510b22003-06-25 00:07:40 +00001297
bellardc20709a2004-04-21 23:27:19 +00001298void hex_dump(FILE *f, const uint8_t *buf, int size)
bellard67b915a2004-03-31 23:37:16 +00001299{
bellardc20709a2004-04-21 23:27:19 +00001300 int len, i, j, c;
1301
1302 for(i=0;i<size;i+=16) {
1303 len = size - i;
1304 if (len > 16)
1305 len = 16;
1306 fprintf(f, "%08x ", i);
1307 for(j=0;j<16;j++) {
1308 if (j < len)
1309 fprintf(f, " %02x", buf[i+j]);
1310 else
1311 fprintf(f, " ");
1312 }
1313 fprintf(f, " ");
1314 for(j=0;j<len;j++) {
1315 c = buf[i+j];
1316 if (c < ' ' || c > '~')
1317 c = '.';
1318 fprintf(f, "%c", c);
1319 }
1320 fprintf(f, "\n");
1321 }
1322}
1323
1324void qemu_send_packet(NetDriverState *nd, const uint8_t *buf, int size)
1325{
1326 nd->send_packet(nd, buf, size);
1327}
1328
1329void qemu_add_read_packet(NetDriverState *nd, IOCanRWHandler *fd_can_read,
1330 IOReadHandler *fd_read, void *opaque)
1331{
1332 nd->add_read_packet(nd, fd_can_read, fd_read, opaque);
1333}
1334
1335/* dummy network adapter */
1336
1337static void dummy_send_packet(NetDriverState *nd, const uint8_t *buf, int size)
1338{
1339}
1340
1341static void dummy_add_read_packet(NetDriverState *nd,
1342 IOCanRWHandler *fd_can_read,
1343 IOReadHandler *fd_read, void *opaque)
1344{
1345}
1346
1347static int net_dummy_init(NetDriverState *nd)
1348{
1349 nd->send_packet = dummy_send_packet;
1350 nd->add_read_packet = dummy_add_read_packet;
1351 pstrcpy(nd->ifname, sizeof(nd->ifname), "dummy");
bellard67b915a2004-03-31 23:37:16 +00001352 return 0;
1353}
1354
bellardc20709a2004-04-21 23:27:19 +00001355#if defined(CONFIG_SLIRP)
1356
1357/* slirp network adapter */
1358
1359static void *slirp_fd_opaque;
1360static IOCanRWHandler *slirp_fd_can_read;
1361static IOReadHandler *slirp_fd_read;
1362static int slirp_inited;
1363
1364int slirp_can_output(void)
bellard67b915a2004-03-31 23:37:16 +00001365{
bellardc20709a2004-04-21 23:27:19 +00001366 return slirp_fd_can_read(slirp_fd_opaque);
bellard67b915a2004-03-31 23:37:16 +00001367}
1368
bellardc20709a2004-04-21 23:27:19 +00001369void slirp_output(const uint8_t *pkt, int pkt_len)
1370{
1371#if 0
1372 printf("output:\n");
1373 hex_dump(stdout, pkt, pkt_len);
1374#endif
1375 slirp_fd_read(slirp_fd_opaque, pkt, pkt_len);
1376}
1377
1378static void slirp_send_packet(NetDriverState *nd, const uint8_t *buf, int size)
1379{
1380#if 0
1381 printf("input:\n");
1382 hex_dump(stdout, buf, size);
1383#endif
1384 slirp_input(buf, size);
1385}
1386
1387static void slirp_add_read_packet(NetDriverState *nd,
1388 IOCanRWHandler *fd_can_read,
1389 IOReadHandler *fd_read, void *opaque)
1390{
1391 slirp_fd_opaque = opaque;
1392 slirp_fd_can_read = fd_can_read;
1393 slirp_fd_read = fd_read;
1394}
1395
1396static int net_slirp_init(NetDriverState *nd)
1397{
1398 if (!slirp_inited) {
1399 slirp_inited = 1;
1400 slirp_init();
1401 }
1402 nd->send_packet = slirp_send_packet;
1403 nd->add_read_packet = slirp_add_read_packet;
1404 pstrcpy(nd->ifname, sizeof(nd->ifname), "slirp");
1405 return 0;
1406}
1407
bellard9bf05442004-08-25 22:12:49 +00001408static int get_str_sep(char *buf, int buf_size, const char **pp, int sep)
1409{
1410 const char *p, *p1;
1411 int len;
1412 p = *pp;
1413 p1 = strchr(p, sep);
1414 if (!p1)
1415 return -1;
1416 len = p1 - p;
1417 p1++;
1418 if (buf_size > 0) {
1419 if (len > buf_size - 1)
1420 len = buf_size - 1;
1421 memcpy(buf, p, len);
1422 buf[len] = '\0';
1423 }
1424 *pp = p1;
1425 return 0;
1426}
1427
1428static void net_slirp_redir(const char *redir_str)
1429{
1430 int is_udp;
1431 char buf[256], *r;
1432 const char *p;
1433 struct in_addr guest_addr;
1434 int host_port, guest_port;
1435
1436 if (!slirp_inited) {
1437 slirp_inited = 1;
1438 slirp_init();
1439 }
1440
1441 p = redir_str;
1442 if (get_str_sep(buf, sizeof(buf), &p, ':') < 0)
1443 goto fail;
1444 if (!strcmp(buf, "tcp")) {
1445 is_udp = 0;
1446 } else if (!strcmp(buf, "udp")) {
1447 is_udp = 1;
1448 } else {
1449 goto fail;
1450 }
1451
1452 if (get_str_sep(buf, sizeof(buf), &p, ':') < 0)
1453 goto fail;
1454 host_port = strtol(buf, &r, 0);
1455 if (r == buf)
1456 goto fail;
1457
1458 if (get_str_sep(buf, sizeof(buf), &p, ':') < 0)
1459 goto fail;
1460 if (buf[0] == '\0') {
1461 pstrcpy(buf, sizeof(buf), "10.0.2.15");
1462 }
1463 if (!inet_aton(buf, &guest_addr))
1464 goto fail;
1465
1466 guest_port = strtol(p, &r, 0);
1467 if (r == p)
1468 goto fail;
1469
1470 if (slirp_redir(is_udp, host_port, guest_addr, guest_port) < 0) {
1471 fprintf(stderr, "qemu: could not set up redirection\n");
1472 exit(1);
1473 }
1474 return;
1475 fail:
1476 fprintf(stderr, "qemu: syntax: -redir [tcp|udp]:host-port:[guest-host]:guest-port\n");
1477 exit(1);
1478}
bellard9d728e82004-09-05 23:09:03 +00001479
bellardc94c8d62004-09-13 21:37:34 +00001480#ifndef _WIN32
1481
bellard9d728e82004-09-05 23:09:03 +00001482char smb_dir[1024];
1483
1484static void smb_exit(void)
1485{
1486 DIR *d;
1487 struct dirent *de;
1488 char filename[1024];
1489
1490 /* erase all the files in the directory */
1491 d = opendir(smb_dir);
1492 for(;;) {
1493 de = readdir(d);
1494 if (!de)
1495 break;
1496 if (strcmp(de->d_name, ".") != 0 &&
1497 strcmp(de->d_name, "..") != 0) {
1498 snprintf(filename, sizeof(filename), "%s/%s",
1499 smb_dir, de->d_name);
1500 unlink(filename);
1501 }
1502 }
bellard03ffbb62004-09-06 00:14:04 +00001503 closedir(d);
bellard9d728e82004-09-05 23:09:03 +00001504 rmdir(smb_dir);
1505}
1506
1507/* automatic user mode samba server configuration */
1508void net_slirp_smb(const char *exported_dir)
1509{
1510 char smb_conf[1024];
1511 char smb_cmdline[1024];
1512 FILE *f;
1513
1514 if (!slirp_inited) {
1515 slirp_inited = 1;
1516 slirp_init();
1517 }
1518
1519 /* XXX: better tmp dir construction */
1520 snprintf(smb_dir, sizeof(smb_dir), "/tmp/qemu-smb.%d", getpid());
1521 if (mkdir(smb_dir, 0700) < 0) {
1522 fprintf(stderr, "qemu: could not create samba server dir '%s'\n", smb_dir);
1523 exit(1);
1524 }
1525 snprintf(smb_conf, sizeof(smb_conf), "%s/%s", smb_dir, "smb.conf");
1526
1527 f = fopen(smb_conf, "w");
1528 if (!f) {
1529 fprintf(stderr, "qemu: could not create samba server configuration file '%s'\n", smb_conf);
1530 exit(1);
1531 }
1532 fprintf(f,
1533 "[global]\n"
1534 "pid directory=%s\n"
1535 "lock directory=%s\n"
1536 "log file=%s/log.smbd\n"
1537 "smb passwd file=%s/smbpasswd\n"
bellard03ffbb62004-09-06 00:14:04 +00001538 "security = share\n"
bellard9d728e82004-09-05 23:09:03 +00001539 "[qemu]\n"
1540 "path=%s\n"
1541 "read only=no\n"
1542 "guest ok=yes\n",
1543 smb_dir,
1544 smb_dir,
1545 smb_dir,
1546 smb_dir,
1547 exported_dir
1548 );
1549 fclose(f);
1550 atexit(smb_exit);
1551
1552 snprintf(smb_cmdline, sizeof(smb_cmdline), "/usr/sbin/smbd -s %s",
1553 smb_conf);
1554
1555 slirp_add_exec(0, smb_cmdline, 4, 139);
1556}
bellard9bf05442004-08-25 22:12:49 +00001557
bellardc94c8d62004-09-13 21:37:34 +00001558#endif /* !defined(_WIN32) */
1559
bellardc20709a2004-04-21 23:27:19 +00001560#endif /* CONFIG_SLIRP */
1561
1562#if !defined(_WIN32)
bellard7d3505c2004-05-12 19:32:15 +00001563#ifdef _BSD
1564static int tun_open(char *ifname, int ifname_size)
1565{
1566 int fd;
1567 char *dev;
1568 struct stat s;
bellard67b915a2004-03-31 23:37:16 +00001569
bellard7d3505c2004-05-12 19:32:15 +00001570 fd = open("/dev/tap", O_RDWR);
1571 if (fd < 0) {
1572 fprintf(stderr, "warning: could not open /dev/tap: no virtual network emulation\n");
1573 return -1;
1574 }
1575
1576 fstat(fd, &s);
1577 dev = devname(s.st_rdev, S_IFCHR);
1578 pstrcpy(ifname, ifname_size, dev);
1579
1580 fcntl(fd, F_SETFL, O_NONBLOCK);
1581 return fd;
1582}
1583#else
bellardc4b1fcc2004-03-14 21:44:30 +00001584static int tun_open(char *ifname, int ifname_size)
bellardf1510b22003-06-25 00:07:40 +00001585{
1586 struct ifreq ifr;
bellardc4b1fcc2004-03-14 21:44:30 +00001587 int fd, ret;
bellardf1510b22003-06-25 00:07:40 +00001588
1589 fd = open("/dev/net/tun", O_RDWR);
1590 if (fd < 0) {
1591 fprintf(stderr, "warning: could not open /dev/net/tun: no virtual network emulation\n");
1592 return -1;
1593 }
1594 memset(&ifr, 0, sizeof(ifr));
1595 ifr.ifr_flags = IFF_TAP | IFF_NO_PI;
1596 pstrcpy(ifr.ifr_name, IFNAMSIZ, "tun%d");
1597 ret = ioctl(fd, TUNSETIFF, (void *) &ifr);
1598 if (ret != 0) {
1599 fprintf(stderr, "warning: could not configure /dev/net/tun: no virtual network emulation\n");
1600 close(fd);
1601 return -1;
1602 }
bellardfc01f7e2003-06-30 10:03:06 +00001603 printf("Connected to host network interface: %s\n", ifr.ifr_name);
bellardc4b1fcc2004-03-14 21:44:30 +00001604 pstrcpy(ifname, ifname_size, ifr.ifr_name);
bellardf1510b22003-06-25 00:07:40 +00001605 fcntl(fd, F_SETFL, O_NONBLOCK);
bellardc4b1fcc2004-03-14 21:44:30 +00001606 return fd;
1607}
bellard7d3505c2004-05-12 19:32:15 +00001608#endif
bellardf1510b22003-06-25 00:07:40 +00001609
bellardc20709a2004-04-21 23:27:19 +00001610static void tun_send_packet(NetDriverState *nd, const uint8_t *buf, int size)
bellardc4b1fcc2004-03-14 21:44:30 +00001611{
bellardc4b1fcc2004-03-14 21:44:30 +00001612 write(nd->fd, buf, size);
bellardf1510b22003-06-25 00:07:40 +00001613}
1614
bellardc20709a2004-04-21 23:27:19 +00001615static void tun_add_read_packet(NetDriverState *nd,
1616 IOCanRWHandler *fd_can_read,
1617 IOReadHandler *fd_read, void *opaque)
1618{
1619 qemu_add_fd_read_handler(nd->fd, fd_can_read, fd_read, opaque);
1620}
1621
1622static int net_tun_init(NetDriverState *nd)
1623{
1624 int pid, status;
1625 char *args[3];
1626 char **parg;
1627
1628 nd->fd = tun_open(nd->ifname, sizeof(nd->ifname));
1629 if (nd->fd < 0)
1630 return -1;
1631
1632 /* try to launch network init script */
1633 pid = fork();
1634 if (pid >= 0) {
1635 if (pid == 0) {
1636 parg = args;
1637 *parg++ = network_script;
1638 *parg++ = nd->ifname;
1639 *parg++ = NULL;
1640 execv(network_script, args);
1641 exit(1);
1642 }
1643 while (waitpid(pid, &status, 0) != pid);
1644 if (!WIFEXITED(status) ||
1645 WEXITSTATUS(status) != 0) {
1646 fprintf(stderr, "%s: could not launch network script\n",
1647 network_script);
1648 }
1649 }
1650 nd->send_packet = tun_send_packet;
1651 nd->add_read_packet = tun_add_read_packet;
1652 return 0;
1653}
1654
1655static int net_fd_init(NetDriverState *nd, int fd)
1656{
1657 nd->fd = fd;
1658 nd->send_packet = tun_send_packet;
1659 nd->add_read_packet = tun_add_read_packet;
1660 pstrcpy(nd->ifname, sizeof(nd->ifname), "tunfd");
1661 return 0;
1662}
1663
1664#endif /* !_WIN32 */
bellard67b915a2004-03-31 23:37:16 +00001665
bellard330d0412003-07-26 18:11:40 +00001666/***********************************************************/
bellard313aa562003-08-10 21:52:11 +00001667/* dumb display */
1668
bellard313aa562003-08-10 21:52:11 +00001669static void dumb_update(DisplayState *ds, int x, int y, int w, int h)
1670{
1671}
1672
1673static void dumb_resize(DisplayState *ds, int w, int h)
1674{
1675}
1676
1677static void dumb_refresh(DisplayState *ds)
1678{
1679 vga_update_display();
1680}
1681
1682void dumb_display_init(DisplayState *ds)
1683{
1684 ds->data = NULL;
1685 ds->linesize = 0;
1686 ds->depth = 0;
1687 ds->dpy_update = dumb_update;
1688 ds->dpy_resize = dumb_resize;
1689 ds->dpy_refresh = dumb_refresh;
1690}
1691
bellard3a51dee2003-10-27 21:18:35 +00001692#if !defined(CONFIG_SOFTMMU)
bellard313aa562003-08-10 21:52:11 +00001693/***********************************************************/
bellard0824d6f2003-06-24 13:42:40 +00001694/* cpu signal handler */
1695static void host_segv_handler(int host_signum, siginfo_t *info,
1696 void *puc)
1697{
1698 if (cpu_signal_handler(host_signum, info, puc))
1699 return;
bellard8d11df92004-08-24 21:13:40 +00001700 if (stdio_nb_clients > 0)
1701 term_exit();
bellard0824d6f2003-06-24 13:42:40 +00001702 abort();
1703}
bellard3a51dee2003-10-27 21:18:35 +00001704#endif
bellard0824d6f2003-06-24 13:42:40 +00001705
bellard8a7ddc32004-03-31 19:00:16 +00001706/***********************************************************/
1707/* I/O handling */
bellard0824d6f2003-06-24 13:42:40 +00001708
bellardc4b1fcc2004-03-14 21:44:30 +00001709#define MAX_IO_HANDLERS 64
1710
1711typedef struct IOHandlerRecord {
1712 int fd;
1713 IOCanRWHandler *fd_can_read;
1714 IOReadHandler *fd_read;
1715 void *opaque;
1716 /* temporary data */
1717 struct pollfd *ufd;
1718 int max_size;
bellard8a7ddc32004-03-31 19:00:16 +00001719 struct IOHandlerRecord *next;
bellardc4b1fcc2004-03-14 21:44:30 +00001720} IOHandlerRecord;
1721
bellard8a7ddc32004-03-31 19:00:16 +00001722static IOHandlerRecord *first_io_handler;
bellardc4b1fcc2004-03-14 21:44:30 +00001723
bellard8a7ddc32004-03-31 19:00:16 +00001724int qemu_add_fd_read_handler(int fd, IOCanRWHandler *fd_can_read,
1725 IOReadHandler *fd_read, void *opaque)
bellardc4b1fcc2004-03-14 21:44:30 +00001726{
1727 IOHandlerRecord *ioh;
1728
bellard8a7ddc32004-03-31 19:00:16 +00001729 ioh = qemu_mallocz(sizeof(IOHandlerRecord));
1730 if (!ioh)
bellardc4b1fcc2004-03-14 21:44:30 +00001731 return -1;
bellardc4b1fcc2004-03-14 21:44:30 +00001732 ioh->fd = fd;
1733 ioh->fd_can_read = fd_can_read;
1734 ioh->fd_read = fd_read;
1735 ioh->opaque = opaque;
bellard8a7ddc32004-03-31 19:00:16 +00001736 ioh->next = first_io_handler;
1737 first_io_handler = ioh;
bellardc4b1fcc2004-03-14 21:44:30 +00001738 return 0;
1739}
1740
bellard8a7ddc32004-03-31 19:00:16 +00001741void qemu_del_fd_read_handler(int fd)
bellardb4608c02003-06-27 17:34:32 +00001742{
bellard8a7ddc32004-03-31 19:00:16 +00001743 IOHandlerRecord **pioh, *ioh;
1744
1745 pioh = &first_io_handler;
1746 for(;;) {
1747 ioh = *pioh;
1748 if (ioh == NULL)
1749 break;
1750 if (ioh->fd == fd) {
1751 *pioh = ioh->next;
1752 break;
1753 }
1754 pioh = &ioh->next;
1755 }
bellardb4608c02003-06-27 17:34:32 +00001756}
1757
bellard8a7ddc32004-03-31 19:00:16 +00001758/***********************************************************/
1759/* savevm/loadvm support */
bellardb4608c02003-06-27 17:34:32 +00001760
bellard8a7ddc32004-03-31 19:00:16 +00001761void qemu_put_buffer(QEMUFile *f, const uint8_t *buf, int size)
1762{
1763 fwrite(buf, 1, size, f);
1764}
1765
1766void qemu_put_byte(QEMUFile *f, int v)
1767{
1768 fputc(v, f);
1769}
1770
1771void qemu_put_be16(QEMUFile *f, unsigned int v)
1772{
1773 qemu_put_byte(f, v >> 8);
1774 qemu_put_byte(f, v);
1775}
1776
1777void qemu_put_be32(QEMUFile *f, unsigned int v)
1778{
1779 qemu_put_byte(f, v >> 24);
1780 qemu_put_byte(f, v >> 16);
1781 qemu_put_byte(f, v >> 8);
1782 qemu_put_byte(f, v);
1783}
1784
1785void qemu_put_be64(QEMUFile *f, uint64_t v)
1786{
1787 qemu_put_be32(f, v >> 32);
1788 qemu_put_be32(f, v);
1789}
1790
1791int qemu_get_buffer(QEMUFile *f, uint8_t *buf, int size)
1792{
1793 return fread(buf, 1, size, f);
1794}
1795
1796int qemu_get_byte(QEMUFile *f)
1797{
1798 int v;
1799 v = fgetc(f);
1800 if (v == EOF)
1801 return 0;
1802 else
1803 return v;
1804}
1805
1806unsigned int qemu_get_be16(QEMUFile *f)
1807{
1808 unsigned int v;
1809 v = qemu_get_byte(f) << 8;
1810 v |= qemu_get_byte(f);
1811 return v;
1812}
1813
1814unsigned int qemu_get_be32(QEMUFile *f)
1815{
1816 unsigned int v;
1817 v = qemu_get_byte(f) << 24;
1818 v |= qemu_get_byte(f) << 16;
1819 v |= qemu_get_byte(f) << 8;
1820 v |= qemu_get_byte(f);
1821 return v;
1822}
1823
1824uint64_t qemu_get_be64(QEMUFile *f)
1825{
1826 uint64_t v;
1827 v = (uint64_t)qemu_get_be32(f) << 32;
1828 v |= qemu_get_be32(f);
1829 return v;
1830}
1831
1832int64_t qemu_ftell(QEMUFile *f)
1833{
1834 return ftell(f);
1835}
1836
1837int64_t qemu_fseek(QEMUFile *f, int64_t pos, int whence)
1838{
1839 if (fseek(f, pos, whence) < 0)
1840 return -1;
1841 return ftell(f);
1842}
1843
1844typedef struct SaveStateEntry {
1845 char idstr[256];
1846 int instance_id;
1847 int version_id;
1848 SaveStateHandler *save_state;
1849 LoadStateHandler *load_state;
1850 void *opaque;
1851 struct SaveStateEntry *next;
1852} SaveStateEntry;
1853
1854static SaveStateEntry *first_se;
1855
1856int register_savevm(const char *idstr,
1857 int instance_id,
1858 int version_id,
1859 SaveStateHandler *save_state,
1860 LoadStateHandler *load_state,
1861 void *opaque)
1862{
1863 SaveStateEntry *se, **pse;
1864
1865 se = qemu_malloc(sizeof(SaveStateEntry));
1866 if (!se)
1867 return -1;
1868 pstrcpy(se->idstr, sizeof(se->idstr), idstr);
1869 se->instance_id = instance_id;
1870 se->version_id = version_id;
1871 se->save_state = save_state;
1872 se->load_state = load_state;
1873 se->opaque = opaque;
1874 se->next = NULL;
1875
1876 /* add at the end of list */
1877 pse = &first_se;
1878 while (*pse != NULL)
1879 pse = &(*pse)->next;
1880 *pse = se;
1881 return 0;
1882}
1883
1884#define QEMU_VM_FILE_MAGIC 0x5145564d
1885#define QEMU_VM_FILE_VERSION 0x00000001
1886
1887int qemu_savevm(const char *filename)
1888{
1889 SaveStateEntry *se;
1890 QEMUFile *f;
1891 int len, len_pos, cur_pos, saved_vm_running, ret;
1892
1893 saved_vm_running = vm_running;
1894 vm_stop(0);
1895
1896 f = fopen(filename, "wb");
1897 if (!f) {
1898 ret = -1;
1899 goto the_end;
bellard313aa562003-08-10 21:52:11 +00001900 }
1901
bellard8a7ddc32004-03-31 19:00:16 +00001902 qemu_put_be32(f, QEMU_VM_FILE_MAGIC);
1903 qemu_put_be32(f, QEMU_VM_FILE_VERSION);
1904
1905 for(se = first_se; se != NULL; se = se->next) {
1906 /* ID string */
1907 len = strlen(se->idstr);
1908 qemu_put_byte(f, len);
1909 qemu_put_buffer(f, se->idstr, len);
1910
1911 qemu_put_be32(f, se->instance_id);
1912 qemu_put_be32(f, se->version_id);
1913
1914 /* record size: filled later */
1915 len_pos = ftell(f);
1916 qemu_put_be32(f, 0);
1917
1918 se->save_state(f, se->opaque);
1919
1920 /* fill record size */
1921 cur_pos = ftell(f);
1922 len = ftell(f) - len_pos - 4;
1923 fseek(f, len_pos, SEEK_SET);
1924 qemu_put_be32(f, len);
1925 fseek(f, cur_pos, SEEK_SET);
1926 }
1927
1928 fclose(f);
1929 ret = 0;
1930 the_end:
1931 if (saved_vm_running)
1932 vm_start();
1933 return ret;
1934}
1935
1936static SaveStateEntry *find_se(const char *idstr, int instance_id)
1937{
1938 SaveStateEntry *se;
1939
1940 for(se = first_se; se != NULL; se = se->next) {
1941 if (!strcmp(se->idstr, idstr) &&
1942 instance_id == se->instance_id)
1943 return se;
1944 }
1945 return NULL;
1946}
1947
1948int qemu_loadvm(const char *filename)
1949{
1950 SaveStateEntry *se;
1951 QEMUFile *f;
1952 int len, cur_pos, ret, instance_id, record_len, version_id;
1953 int saved_vm_running;
1954 unsigned int v;
1955 char idstr[256];
1956
1957 saved_vm_running = vm_running;
1958 vm_stop(0);
1959
1960 f = fopen(filename, "rb");
1961 if (!f) {
1962 ret = -1;
1963 goto the_end;
1964 }
1965
1966 v = qemu_get_be32(f);
1967 if (v != QEMU_VM_FILE_MAGIC)
1968 goto fail;
1969 v = qemu_get_be32(f);
1970 if (v != QEMU_VM_FILE_VERSION) {
1971 fail:
1972 fclose(f);
1973 ret = -1;
1974 goto the_end;
1975 }
bellardb4608c02003-06-27 17:34:32 +00001976 for(;;) {
bellarda541f292004-04-12 20:39:29 +00001977#if defined (DO_TB_FLUSH)
bellardd9276372004-04-26 19:44:57 +00001978 tb_flush(global_env);
bellarda541f292004-04-12 20:39:29 +00001979#endif
bellard8a7ddc32004-03-31 19:00:16 +00001980 len = qemu_get_byte(f);
1981 if (feof(f))
1982 break;
1983 qemu_get_buffer(f, idstr, len);
1984 idstr[len] = '\0';
1985 instance_id = qemu_get_be32(f);
1986 version_id = qemu_get_be32(f);
1987 record_len = qemu_get_be32(f);
1988#if 0
1989 printf("idstr=%s instance=0x%x version=%d len=%d\n",
1990 idstr, instance_id, version_id, record_len);
bellardc45886d2004-01-05 00:02:06 +00001991#endif
bellard8a7ddc32004-03-31 19:00:16 +00001992 cur_pos = ftell(f);
1993 se = find_se(idstr, instance_id);
1994 if (!se) {
1995 fprintf(stderr, "qemu: warning: instance 0x%x of device '%s' not present in current VM\n",
1996 instance_id, idstr);
1997 } else {
1998 ret = se->load_state(f, se->opaque, version_id);
1999 if (ret < 0) {
2000 fprintf(stderr, "qemu: warning: error while loading state for instance 0x%x of device '%s'\n",
2001 instance_id, idstr);
2002 }
bellard34865132003-10-05 14:28:56 +00002003 }
bellard8a7ddc32004-03-31 19:00:16 +00002004 /* always seek to exact end of record */
2005 qemu_fseek(f, cur_pos + record_len, SEEK_SET);
2006 }
2007 fclose(f);
2008 ret = 0;
2009 the_end:
2010 if (saved_vm_running)
2011 vm_start();
2012 return ret;
2013}
2014
2015/***********************************************************/
2016/* cpu save/restore */
2017
2018#if defined(TARGET_I386)
2019
2020static void cpu_put_seg(QEMUFile *f, SegmentCache *dt)
2021{
bellard02ba45c2004-06-25 14:46:23 +00002022 qemu_put_be32(f, dt->selector);
bellard8a7ddc32004-03-31 19:00:16 +00002023 qemu_put_be32(f, (uint32_t)dt->base);
2024 qemu_put_be32(f, dt->limit);
2025 qemu_put_be32(f, dt->flags);
2026}
2027
2028static void cpu_get_seg(QEMUFile *f, SegmentCache *dt)
2029{
bellard02ba45c2004-06-25 14:46:23 +00002030 dt->selector = qemu_get_be32(f);
bellard8a7ddc32004-03-31 19:00:16 +00002031 dt->base = (uint8_t *)qemu_get_be32(f);
2032 dt->limit = qemu_get_be32(f);
2033 dt->flags = qemu_get_be32(f);
2034}
2035
2036void cpu_save(QEMUFile *f, void *opaque)
2037{
2038 CPUState *env = opaque;
2039 uint16_t fptag, fpus, fpuc;
2040 uint32_t hflags;
2041 int i;
2042
2043 for(i = 0; i < 8; i++)
2044 qemu_put_be32s(f, &env->regs[i]);
2045 qemu_put_be32s(f, &env->eip);
2046 qemu_put_be32s(f, &env->eflags);
2047 qemu_put_be32s(f, &env->eflags);
2048 hflags = env->hflags; /* XXX: suppress most of the redundant hflags */
2049 qemu_put_be32s(f, &hflags);
2050
2051 /* FPU */
2052 fpuc = env->fpuc;
2053 fpus = (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11;
2054 fptag = 0;
2055 for (i=7; i>=0; i--) {
2056 fptag <<= 2;
2057 if (env->fptags[i]) {
2058 fptag |= 3;
bellard34865132003-10-05 14:28:56 +00002059 }
bellard8a7ddc32004-03-31 19:00:16 +00002060 }
2061
2062 qemu_put_be16s(f, &fpuc);
2063 qemu_put_be16s(f, &fpus);
2064 qemu_put_be16s(f, &fptag);
2065
2066 for(i = 0; i < 8; i++) {
2067 uint64_t mant;
2068 uint16_t exp;
2069 cpu_get_fp80(&mant, &exp, env->fpregs[i]);
2070 qemu_put_be64(f, mant);
2071 qemu_put_be16(f, exp);
2072 }
2073
2074 for(i = 0; i < 6; i++)
2075 cpu_put_seg(f, &env->segs[i]);
2076 cpu_put_seg(f, &env->ldt);
2077 cpu_put_seg(f, &env->tr);
2078 cpu_put_seg(f, &env->gdt);
2079 cpu_put_seg(f, &env->idt);
2080
2081 qemu_put_be32s(f, &env->sysenter_cs);
2082 qemu_put_be32s(f, &env->sysenter_esp);
2083 qemu_put_be32s(f, &env->sysenter_eip);
2084
2085 qemu_put_be32s(f, &env->cr[0]);
2086 qemu_put_be32s(f, &env->cr[2]);
2087 qemu_put_be32s(f, &env->cr[3]);
2088 qemu_put_be32s(f, &env->cr[4]);
2089
2090 for(i = 0; i < 8; i++)
2091 qemu_put_be32s(f, &env->dr[i]);
2092
2093 /* MMU */
2094 qemu_put_be32s(f, &env->a20_mask);
2095}
2096
2097int cpu_load(QEMUFile *f, void *opaque, int version_id)
2098{
2099 CPUState *env = opaque;
2100 int i;
2101 uint32_t hflags;
2102 uint16_t fpus, fpuc, fptag;
2103
bellard02ba45c2004-06-25 14:46:23 +00002104 if (version_id != 2)
bellard8a7ddc32004-03-31 19:00:16 +00002105 return -EINVAL;
2106 for(i = 0; i < 8; i++)
2107 qemu_get_be32s(f, &env->regs[i]);
2108 qemu_get_be32s(f, &env->eip);
2109 qemu_get_be32s(f, &env->eflags);
2110 qemu_get_be32s(f, &env->eflags);
2111 qemu_get_be32s(f, &hflags);
2112
2113 qemu_get_be16s(f, &fpuc);
2114 qemu_get_be16s(f, &fpus);
2115 qemu_get_be16s(f, &fptag);
2116
2117 for(i = 0; i < 8; i++) {
2118 uint64_t mant;
2119 uint16_t exp;
2120 mant = qemu_get_be64(f);
2121 exp = qemu_get_be16(f);
2122 env->fpregs[i] = cpu_set_fp80(mant, exp);
2123 }
2124
2125 env->fpuc = fpuc;
2126 env->fpstt = (fpus >> 11) & 7;
2127 env->fpus = fpus & ~0x3800;
2128 for(i = 0; i < 8; i++) {
2129 env->fptags[i] = ((fptag & 3) == 3);
2130 fptag >>= 2;
2131 }
2132
2133 for(i = 0; i < 6; i++)
2134 cpu_get_seg(f, &env->segs[i]);
2135 cpu_get_seg(f, &env->ldt);
2136 cpu_get_seg(f, &env->tr);
2137 cpu_get_seg(f, &env->gdt);
2138 cpu_get_seg(f, &env->idt);
2139
2140 qemu_get_be32s(f, &env->sysenter_cs);
2141 qemu_get_be32s(f, &env->sysenter_esp);
2142 qemu_get_be32s(f, &env->sysenter_eip);
2143
2144 qemu_get_be32s(f, &env->cr[0]);
2145 qemu_get_be32s(f, &env->cr[2]);
2146 qemu_get_be32s(f, &env->cr[3]);
2147 qemu_get_be32s(f, &env->cr[4]);
2148
2149 for(i = 0; i < 8; i++)
2150 qemu_get_be32s(f, &env->dr[i]);
2151
2152 /* MMU */
2153 qemu_get_be32s(f, &env->a20_mask);
2154
2155 /* XXX: compute hflags from scratch, except for CPL and IIF */
2156 env->hflags = hflags;
2157 tlb_flush(env, 1);
2158 return 0;
2159}
2160
bellarda541f292004-04-12 20:39:29 +00002161#elif defined(TARGET_PPC)
2162void cpu_save(QEMUFile *f, void *opaque)
2163{
2164}
2165
2166int cpu_load(QEMUFile *f, void *opaque, int version_id)
2167{
2168 return 0;
2169}
bellarde95c8d52004-09-30 22:22:08 +00002170#elif defined(TARGET_SPARC)
2171void cpu_save(QEMUFile *f, void *opaque)
2172{
2173}
2174
2175int cpu_load(QEMUFile *f, void *opaque, int version_id)
2176{
2177 return 0;
2178}
bellard8a7ddc32004-03-31 19:00:16 +00002179#else
2180
2181#warning No CPU save/restore functions
2182
2183#endif
2184
2185/***********************************************************/
2186/* ram save/restore */
2187
2188/* we just avoid storing empty pages */
2189static void ram_put_page(QEMUFile *f, const uint8_t *buf, int len)
2190{
2191 int i, v;
2192
2193 v = buf[0];
2194 for(i = 1; i < len; i++) {
2195 if (buf[i] != v)
2196 goto normal_save;
2197 }
2198 qemu_put_byte(f, 1);
2199 qemu_put_byte(f, v);
2200 return;
2201 normal_save:
2202 qemu_put_byte(f, 0);
2203 qemu_put_buffer(f, buf, len);
2204}
2205
2206static int ram_get_page(QEMUFile *f, uint8_t *buf, int len)
2207{
2208 int v;
2209
2210 v = qemu_get_byte(f);
2211 switch(v) {
2212 case 0:
2213 if (qemu_get_buffer(f, buf, len) != len)
2214 return -EIO;
2215 break;
2216 case 1:
2217 v = qemu_get_byte(f);
2218 memset(buf, v, len);
2219 break;
2220 default:
2221 return -EINVAL;
2222 }
2223 return 0;
2224}
2225
2226static void ram_save(QEMUFile *f, void *opaque)
2227{
2228 int i;
2229 qemu_put_be32(f, phys_ram_size);
2230 for(i = 0; i < phys_ram_size; i+= TARGET_PAGE_SIZE) {
2231 ram_put_page(f, phys_ram_base + i, TARGET_PAGE_SIZE);
2232 }
2233}
2234
2235static int ram_load(QEMUFile *f, void *opaque, int version_id)
2236{
2237 int i, ret;
2238
2239 if (version_id != 1)
2240 return -EINVAL;
2241 if (qemu_get_be32(f) != phys_ram_size)
2242 return -EINVAL;
2243 for(i = 0; i < phys_ram_size; i+= TARGET_PAGE_SIZE) {
2244 ret = ram_get_page(f, phys_ram_base + i, TARGET_PAGE_SIZE);
2245 if (ret)
2246 return ret;
2247 }
2248 return 0;
2249}
2250
2251/***********************************************************/
2252/* main execution loop */
2253
2254void gui_update(void *opaque)
2255{
2256 display_state.dpy_refresh(&display_state);
2257 qemu_mod_timer(gui_timer, GUI_REFRESH_INTERVAL + qemu_get_clock(rt_clock));
2258}
2259
2260/* XXX: support several handlers */
2261VMStopHandler *vm_stop_cb;
2262VMStopHandler *vm_stop_opaque;
2263
2264int qemu_add_vm_stop_handler(VMStopHandler *cb, void *opaque)
2265{
2266 vm_stop_cb = cb;
2267 vm_stop_opaque = opaque;
2268 return 0;
2269}
2270
2271void qemu_del_vm_stop_handler(VMStopHandler *cb, void *opaque)
2272{
2273 vm_stop_cb = NULL;
2274}
2275
2276void vm_start(void)
2277{
2278 if (!vm_running) {
2279 cpu_enable_ticks();
2280 vm_running = 1;
2281 }
2282}
2283
2284void vm_stop(int reason)
2285{
2286 if (vm_running) {
2287 cpu_disable_ticks();
2288 vm_running = 0;
2289 if (reason != 0) {
2290 if (vm_stop_cb) {
2291 vm_stop_cb(vm_stop_opaque, reason);
2292 }
2293 }
2294 }
2295}
2296
bellardbb0c6722004-06-20 12:37:32 +00002297/* reset/shutdown handler */
2298
2299typedef struct QEMUResetEntry {
2300 QEMUResetHandler *func;
2301 void *opaque;
2302 struct QEMUResetEntry *next;
2303} QEMUResetEntry;
2304
2305static QEMUResetEntry *first_reset_entry;
2306static int reset_requested;
2307static int shutdown_requested;
2308
2309void qemu_register_reset(QEMUResetHandler *func, void *opaque)
2310{
2311 QEMUResetEntry **pre, *re;
2312
2313 pre = &first_reset_entry;
2314 while (*pre != NULL)
2315 pre = &(*pre)->next;
2316 re = qemu_mallocz(sizeof(QEMUResetEntry));
2317 re->func = func;
2318 re->opaque = opaque;
2319 re->next = NULL;
2320 *pre = re;
2321}
2322
2323void qemu_system_reset(void)
2324{
2325 QEMUResetEntry *re;
2326
2327 /* reset all devices */
2328 for(re = first_reset_entry; re != NULL; re = re->next) {
2329 re->func(re->opaque);
2330 }
2331}
2332
2333void qemu_system_reset_request(void)
2334{
2335 reset_requested = 1;
2336 cpu_interrupt(cpu_single_env, CPU_INTERRUPT_EXIT);
2337}
2338
2339void qemu_system_shutdown_request(void)
2340{
2341 shutdown_requested = 1;
2342 cpu_interrupt(cpu_single_env, CPU_INTERRUPT_EXIT);
2343}
2344
2345static void main_cpu_reset(void *opaque)
2346{
2347#ifdef TARGET_I386
2348 CPUState *env = opaque;
2349 cpu_reset(env);
2350#endif
2351}
2352
bellard5905b2e2004-08-01 21:53:26 +00002353void main_loop_wait(int timeout)
bellard8a7ddc32004-03-31 19:00:16 +00002354{
bellard67b915a2004-03-31 23:37:16 +00002355#ifndef _WIN32
bellard8a7ddc32004-03-31 19:00:16 +00002356 struct pollfd ufds[MAX_IO_HANDLERS + 1], *pf;
bellard8a7ddc32004-03-31 19:00:16 +00002357 IOHandlerRecord *ioh, *ioh_next;
bellard67b915a2004-03-31 23:37:16 +00002358 uint8_t buf[4096];
2359 int n, max_size;
2360#endif
bellard5905b2e2004-08-01 21:53:26 +00002361 int ret;
bellardc4b1fcc2004-03-14 21:44:30 +00002362
bellard38e205a2004-04-06 19:29:17 +00002363#ifdef _WIN32
2364 if (timeout > 0)
2365 Sleep(timeout);
2366#else
bellardb4608c02003-06-27 17:34:32 +00002367 /* poll any events */
bellard8a7ddc32004-03-31 19:00:16 +00002368 /* XXX: separate device handlers from system ones */
bellardb4608c02003-06-27 17:34:32 +00002369 pf = ufds;
bellard8a7ddc32004-03-31 19:00:16 +00002370 for(ioh = first_io_handler; ioh != NULL; ioh = ioh->next) {
2371 if (!ioh->fd_can_read) {
2372 max_size = 0;
bellardc4b1fcc2004-03-14 21:44:30 +00002373 pf->fd = ioh->fd;
2374 pf->events = POLLIN;
2375 ioh->ufd = pf;
2376 pf++;
2377 } else {
bellard8a7ddc32004-03-31 19:00:16 +00002378 max_size = ioh->fd_can_read(ioh->opaque);
2379 if (max_size > 0) {
2380 if (max_size > sizeof(buf))
2381 max_size = sizeof(buf);
2382 pf->fd = ioh->fd;
2383 pf->events = POLLIN;
2384 ioh->ufd = pf;
2385 pf++;
2386 } else {
2387 ioh->ufd = NULL;
2388 }
bellardc4b1fcc2004-03-14 21:44:30 +00002389 }
2390 ioh->max_size = max_size;
bellardb4608c02003-06-27 17:34:32 +00002391 }
bellard73332e52004-04-04 20:22:28 +00002392
bellardb4608c02003-06-27 17:34:32 +00002393 ret = poll(ufds, pf - ufds, timeout);
2394 if (ret > 0) {
bellard8a7ddc32004-03-31 19:00:16 +00002395 /* XXX: better handling of removal */
2396 for(ioh = first_io_handler; ioh != NULL; ioh = ioh_next) {
2397 ioh_next = ioh->next;
bellardc4b1fcc2004-03-14 21:44:30 +00002398 pf = ioh->ufd;
2399 if (pf) {
bellard8a7ddc32004-03-31 19:00:16 +00002400 if (pf->revents & POLLIN) {
2401 if (ioh->max_size == 0) {
2402 /* just a read event */
2403 ioh->fd_read(ioh->opaque, NULL, 0);
2404 } else {
2405 n = read(ioh->fd, buf, ioh->max_size);
2406 if (n >= 0) {
2407 ioh->fd_read(ioh->opaque, buf, n);
bellard158156d2004-05-17 21:13:42 +00002408 } else if (errno != EAGAIN) {
bellard8a7ddc32004-03-31 19:00:16 +00002409 ioh->fd_read(ioh->opaque, NULL, -errno);
2410 }
2411 }
bellardb4608c02003-06-27 17:34:32 +00002412 }
bellardb4608c02003-06-27 17:34:32 +00002413 }
bellardb4608c02003-06-27 17:34:32 +00002414 }
2415 }
bellard5905b2e2004-08-01 21:53:26 +00002416#endif /* !defined(_WIN32) */
bellardc20709a2004-04-21 23:27:19 +00002417#if defined(CONFIG_SLIRP)
2418 /* XXX: merge with poll() */
2419 if (slirp_inited) {
2420 fd_set rfds, wfds, xfds;
2421 int nfds;
2422 struct timeval tv;
2423
2424 nfds = -1;
2425 FD_ZERO(&rfds);
2426 FD_ZERO(&wfds);
2427 FD_ZERO(&xfds);
2428 slirp_select_fill(&nfds, &rfds, &wfds, &xfds);
2429 tv.tv_sec = 0;
2430 tv.tv_usec = 0;
2431 ret = select(nfds + 1, &rfds, &wfds, &xfds, &tv);
2432 if (ret >= 0) {
2433 slirp_select_poll(&rfds, &wfds, &xfds);
2434 }
2435 }
2436#endif
2437
bellard8a7ddc32004-03-31 19:00:16 +00002438 if (vm_running) {
2439 qemu_run_timers(&active_timers[QEMU_TIMER_VIRTUAL],
2440 qemu_get_clock(vm_clock));
2441
bellardaaaa7df2004-04-26 20:56:53 +00002442 if (audio_enabled) {
2443 /* XXX: add explicit timer */
2444 SB16_run();
2445 }
bellard8a7ddc32004-03-31 19:00:16 +00002446
2447 /* run dma transfers, if any */
2448 DMA_run();
bellardb4608c02003-06-27 17:34:32 +00002449 }
bellard8dc75d72004-02-25 23:30:56 +00002450
bellard8a7ddc32004-03-31 19:00:16 +00002451 /* real time timers */
2452 qemu_run_timers(&active_timers[QEMU_TIMER_REALTIME],
2453 qemu_get_clock(rt_clock));
bellard5905b2e2004-08-01 21:53:26 +00002454}
2455
2456int main_loop(void)
2457{
2458 int ret, timeout;
2459 CPUState *env = global_env;
2460
2461 for(;;) {
2462 if (vm_running) {
2463 ret = cpu_exec(env);
2464 if (shutdown_requested) {
2465 ret = EXCP_INTERRUPT;
2466 break;
2467 }
2468 if (reset_requested) {
2469 reset_requested = 0;
2470 qemu_system_reset();
2471 ret = EXCP_INTERRUPT;
2472 }
2473 if (ret == EXCP_DEBUG) {
2474 vm_stop(EXCP_DEBUG);
2475 }
2476 /* if hlt instruction, we wait until the next IRQ */
2477 /* XXX: use timeout computed from timers */
2478 if (ret == EXCP_HLT)
2479 timeout = 10;
2480 else
2481 timeout = 0;
2482 } else {
2483 timeout = 10;
2484 }
2485 main_loop_wait(timeout);
bellardb4608c02003-06-27 17:34:32 +00002486 }
bellard34865132003-10-05 14:28:56 +00002487 cpu_disable_ticks();
2488 return ret;
bellardb4608c02003-06-27 17:34:32 +00002489}
2490
bellard0824d6f2003-06-24 13:42:40 +00002491void help(void)
2492{
bellardaaaa7df2004-04-26 20:56:53 +00002493 printf("QEMU PC emulator version " QEMU_VERSION ", Copyright (c) 2003-2004 Fabrice Bellard\n"
bellard0db63472003-10-27 21:37:46 +00002494 "usage: %s [options] [disk_image]\n"
bellard0824d6f2003-06-24 13:42:40 +00002495 "\n"
bellarda20dd502003-09-30 21:07:02 +00002496 "'disk_image' is a raw hard image image for IDE hard disk 0\n"
bellardfc01f7e2003-06-30 10:03:06 +00002497 "\n"
bellarda20dd502003-09-30 21:07:02 +00002498 "Standard options:\n"
bellardc45886d2004-01-05 00:02:06 +00002499 "-fda/-fdb file use 'file' as floppy disk 0/1 image\n"
bellard36b486b2003-11-11 13:36:08 +00002500 "-hda/-hdb file use 'file' as IDE hard disk 0/1 image\n"
2501 "-hdc/-hdd file use 'file' as IDE hard disk 2/3 image\n"
bellardc4b1fcc2004-03-14 21:44:30 +00002502 "-cdrom file use 'file' as IDE cdrom image (cdrom is ide1 master)\n"
bellard6e44ba72004-01-18 21:56:49 +00002503 "-boot [a|b|c|d] boot on floppy (a, b), hard disk (c) or CD-ROM (d)\n"
bellarda20dd502003-09-30 21:07:02 +00002504 "-snapshot write to temporary files instead of disk image files\n"
bellarda00bad72004-05-22 21:39:06 +00002505 "-m megs set virtual RAM size to megs MB [default=%d]\n"
bellardc4b1fcc2004-03-14 21:44:30 +00002506 "-nographic disable graphical output and redirect serial I/Os to console\n"
bellardaaaa7df2004-04-26 20:56:53 +00002507 "-enable-audio enable audio support\n"
bellard89980282004-06-03 14:04:03 +00002508 "-localtime set the real time clock to local time [default=utc]\n"
bellardd63d3072004-10-03 13:29:03 +00002509 "-full-screen start in full screen\n"
bellardbb0c6722004-06-20 12:37:32 +00002510#ifdef TARGET_PPC
2511 "-prep Simulate a PREP system (default is PowerMAC)\n"
bellarde9b137c2004-06-21 16:46:10 +00002512 "-g WxH[xDEPTH] Set the initial VGA graphic mode\n"
bellardbb0c6722004-06-20 12:37:32 +00002513#endif
bellarda20dd502003-09-30 21:07:02 +00002514 "\n"
bellardc4b1fcc2004-03-14 21:44:30 +00002515 "Network options:\n"
bellardc20709a2004-04-21 23:27:19 +00002516 "-nics n simulate 'n' network cards [default=1]\n"
bellard702c6512004-04-02 21:21:32 +00002517 "-macaddr addr set the mac address of the first interface\n"
bellardc20709a2004-04-21 23:27:19 +00002518 "-n script set tap/tun network init script [default=%s]\n"
2519 "-tun-fd fd use this fd as already opened tap/tun interface\n"
2520#ifdef CONFIG_SLIRP
2521 "-user-net use user mode network stack [default if no tap/tun script]\n"
bellard9bf05442004-08-25 22:12:49 +00002522 "-tftp prefix allow tftp access to files starting with prefix [-user-net]\n"
bellardc94c8d62004-09-13 21:37:34 +00002523#ifndef _WIN32
bellard9d728e82004-09-05 23:09:03 +00002524 "-smb dir allow SMB access to files in 'dir' [-user-net]\n"
bellardc94c8d62004-09-13 21:37:34 +00002525#endif
bellard9bf05442004-08-25 22:12:49 +00002526 "-redir [tcp|udp]:host-port:[guest-host]:guest-port\n"
2527 " redirect TCP or UDP connections from host to guest [-user-net]\n"
bellardc20709a2004-04-21 23:27:19 +00002528#endif
2529 "-dummy-net use dummy network stack\n"
bellardc4b1fcc2004-03-14 21:44:30 +00002530 "\n"
2531 "Linux boot specific:\n"
bellarda20dd502003-09-30 21:07:02 +00002532 "-kernel bzImage use 'bzImage' as kernel image\n"
2533 "-append cmdline use 'cmdline' as kernel command line\n"
2534 "-initrd file use 'file' as initial ram disk\n"
bellardfc01f7e2003-06-30 10:03:06 +00002535 "\n"
bellard330d0412003-07-26 18:11:40 +00002536 "Debug/Expert options:\n"
bellard82c643f2004-07-14 17:28:13 +00002537 "-monitor dev redirect the monitor to char device 'dev'\n"
2538 "-serial dev redirect the serial port to char device 'dev'\n"
bellardcd6f1162004-05-13 22:02:20 +00002539 "-S freeze CPU at startup (use 'c' to start execution)\n"
bellarda20dd502003-09-30 21:07:02 +00002540 "-s wait gdb connection to port %d\n"
2541 "-p port change gdb connection port\n"
bellardf193c792004-03-21 17:06:25 +00002542 "-d item1,... output log to %s (use -d ? for a list of log items)\n"
bellarda20dd502003-09-30 21:07:02 +00002543 "-hdachs c,h,s force hard disk 0 geometry (usually qemu can guess it)\n"
2544 "-L path set the directory for the BIOS and VGA BIOS\n"
bellard77fef8c2004-02-16 22:05:46 +00002545#ifdef USE_CODE_COPY
2546 "-no-code-copy disable code copy acceleration\n"
2547#endif
bellardbb0c6722004-06-20 12:37:32 +00002548#ifdef TARGET_I386
2549 "-isa simulate an ISA-only system (default is PCI system)\n"
bellard1bfe8562004-07-08 21:17:50 +00002550 "-std-vga simulate a standard VGA card with VESA Bochs Extensions\n"
2551 " (default is CL-GD5446 PCI VGA)\n"
bellardbb0c6722004-06-20 12:37:32 +00002552#endif
bellardd63d3072004-10-03 13:29:03 +00002553 "-loadvm file start right away with a saved state (loadvm in monitor)\n"
bellard0824d6f2003-06-24 13:42:40 +00002554 "\n"
bellard82c643f2004-07-14 17:28:13 +00002555 "During emulation, the following keys are useful:\n"
bellard032a8c92004-10-09 22:56:44 +00002556 "ctrl-alt-f toggle full screen\n"
2557 "ctrl-alt-n switch to virtual console 'n'\n"
2558 "ctrl-alt toggle mouse and keyboard grab\n"
bellard82c643f2004-07-14 17:28:13 +00002559 "\n"
2560 "When using -nographic, press 'ctrl-a h' to get some help.\n"
2561 ,
bellard0db63472003-10-27 21:37:46 +00002562#ifdef CONFIG_SOFTMMU
2563 "qemu",
2564#else
2565 "qemu-fast",
2566#endif
bellarda00bad72004-05-22 21:39:06 +00002567 DEFAULT_RAM_SIZE,
2568 DEFAULT_NETWORK_SCRIPT,
bellard6e44ba72004-01-18 21:56:49 +00002569 DEFAULT_GDBSTUB_PORT,
2570 "/tmp/qemu.log");
bellard0db63472003-10-27 21:37:46 +00002571#ifndef CONFIG_SOFTMMU
2572 printf("\n"
2573 "NOTE: this version of QEMU is faster but it needs slightly patched OSes to\n"
2574 "work. Please use the 'qemu' executable to have a more accurate (but slower)\n"
2575 "PC emulation.\n");
2576#endif
bellard0824d6f2003-06-24 13:42:40 +00002577 exit(1);
2578}
2579
bellardcd6f1162004-05-13 22:02:20 +00002580#define HAS_ARG 0x0001
2581
2582enum {
2583 QEMU_OPTION_h,
2584
2585 QEMU_OPTION_fda,
2586 QEMU_OPTION_fdb,
2587 QEMU_OPTION_hda,
2588 QEMU_OPTION_hdb,
2589 QEMU_OPTION_hdc,
2590 QEMU_OPTION_hdd,
2591 QEMU_OPTION_cdrom,
2592 QEMU_OPTION_boot,
2593 QEMU_OPTION_snapshot,
2594 QEMU_OPTION_m,
2595 QEMU_OPTION_nographic,
2596 QEMU_OPTION_enable_audio,
2597
2598 QEMU_OPTION_nics,
2599 QEMU_OPTION_macaddr,
2600 QEMU_OPTION_n,
2601 QEMU_OPTION_tun_fd,
2602 QEMU_OPTION_user_net,
bellardc7f74642004-08-24 21:57:12 +00002603 QEMU_OPTION_tftp,
bellard9d728e82004-09-05 23:09:03 +00002604 QEMU_OPTION_smb,
bellard9bf05442004-08-25 22:12:49 +00002605 QEMU_OPTION_redir,
bellardcd6f1162004-05-13 22:02:20 +00002606 QEMU_OPTION_dummy_net,
2607
2608 QEMU_OPTION_kernel,
2609 QEMU_OPTION_append,
2610 QEMU_OPTION_initrd,
2611
2612 QEMU_OPTION_S,
2613 QEMU_OPTION_s,
2614 QEMU_OPTION_p,
2615 QEMU_OPTION_d,
2616 QEMU_OPTION_hdachs,
2617 QEMU_OPTION_L,
2618 QEMU_OPTION_no_code_copy,
bellard69b91032004-05-18 23:05:28 +00002619 QEMU_OPTION_pci,
bellardbb0c6722004-06-20 12:37:32 +00002620 QEMU_OPTION_isa,
bellard77d4bc32004-05-26 22:13:53 +00002621 QEMU_OPTION_prep,
bellardee22c2f2004-06-03 12:49:50 +00002622 QEMU_OPTION_localtime,
bellard1f042752004-06-05 13:46:47 +00002623 QEMU_OPTION_cirrusvga,
bellarde9b137c2004-06-21 16:46:10 +00002624 QEMU_OPTION_g,
bellard1bfe8562004-07-08 21:17:50 +00002625 QEMU_OPTION_std_vga,
bellard82c643f2004-07-14 17:28:13 +00002626 QEMU_OPTION_monitor,
2627 QEMU_OPTION_serial,
bellardd63d3072004-10-03 13:29:03 +00002628 QEMU_OPTION_loadvm,
2629 QEMU_OPTION_full_screen,
bellardcd6f1162004-05-13 22:02:20 +00002630};
2631
2632typedef struct QEMUOption {
2633 const char *name;
2634 int flags;
2635 int index;
2636} QEMUOption;
2637
2638const QEMUOption qemu_options[] = {
2639 { "h", 0, QEMU_OPTION_h },
2640
2641 { "fda", HAS_ARG, QEMU_OPTION_fda },
2642 { "fdb", HAS_ARG, QEMU_OPTION_fdb },
2643 { "hda", HAS_ARG, QEMU_OPTION_hda },
2644 { "hdb", HAS_ARG, QEMU_OPTION_hdb },
2645 { "hdc", HAS_ARG, QEMU_OPTION_hdc },
2646 { "hdd", HAS_ARG, QEMU_OPTION_hdd },
2647 { "cdrom", HAS_ARG, QEMU_OPTION_cdrom },
2648 { "boot", HAS_ARG, QEMU_OPTION_boot },
2649 { "snapshot", 0, QEMU_OPTION_snapshot },
2650 { "m", HAS_ARG, QEMU_OPTION_m },
2651 { "nographic", 0, QEMU_OPTION_nographic },
2652 { "enable-audio", 0, QEMU_OPTION_enable_audio },
2653
2654 { "nics", HAS_ARG, QEMU_OPTION_nics},
2655 { "macaddr", HAS_ARG, QEMU_OPTION_macaddr},
bellard69b91032004-05-18 23:05:28 +00002656 { "n", HAS_ARG, QEMU_OPTION_n },
bellardcd6f1162004-05-13 22:02:20 +00002657 { "tun-fd", HAS_ARG, QEMU_OPTION_tun_fd },
bellard158156d2004-05-17 21:13:42 +00002658#ifdef CONFIG_SLIRP
bellardcd6f1162004-05-13 22:02:20 +00002659 { "user-net", 0, QEMU_OPTION_user_net },
bellardc7f74642004-08-24 21:57:12 +00002660 { "tftp", HAS_ARG, QEMU_OPTION_tftp },
bellardc94c8d62004-09-13 21:37:34 +00002661#ifndef _WIN32
bellard9d728e82004-09-05 23:09:03 +00002662 { "smb", HAS_ARG, QEMU_OPTION_smb },
bellardc94c8d62004-09-13 21:37:34 +00002663#endif
bellard9bf05442004-08-25 22:12:49 +00002664 { "redir", HAS_ARG, QEMU_OPTION_redir },
bellard158156d2004-05-17 21:13:42 +00002665#endif
bellardcd6f1162004-05-13 22:02:20 +00002666 { "dummy-net", 0, QEMU_OPTION_dummy_net },
2667
2668 { "kernel", HAS_ARG, QEMU_OPTION_kernel },
2669 { "append", HAS_ARG, QEMU_OPTION_append },
2670 { "initrd", HAS_ARG, QEMU_OPTION_initrd },
2671
2672 { "S", 0, QEMU_OPTION_S },
2673 { "s", 0, QEMU_OPTION_s },
2674 { "p", HAS_ARG, QEMU_OPTION_p },
2675 { "d", HAS_ARG, QEMU_OPTION_d },
2676 { "hdachs", HAS_ARG, QEMU_OPTION_hdachs },
2677 { "L", HAS_ARG, QEMU_OPTION_L },
2678 { "no-code-copy", 0, QEMU_OPTION_no_code_copy },
bellard77d4bc32004-05-26 22:13:53 +00002679#ifdef TARGET_PPC
2680 { "prep", 0, QEMU_OPTION_prep },
bellarde9b137c2004-06-21 16:46:10 +00002681 { "g", 1, QEMU_OPTION_g },
bellard77d4bc32004-05-26 22:13:53 +00002682#endif
bellardee22c2f2004-06-03 12:49:50 +00002683 { "localtime", 0, QEMU_OPTION_localtime },
bellardbb0c6722004-06-20 12:37:32 +00002684 { "isa", 0, QEMU_OPTION_isa },
bellard1bfe8562004-07-08 21:17:50 +00002685 { "std-vga", 0, QEMU_OPTION_std_vga },
bellard82c643f2004-07-14 17:28:13 +00002686 { "monitor", 1, QEMU_OPTION_monitor },
2687 { "serial", 1, QEMU_OPTION_serial },
bellardd63d3072004-10-03 13:29:03 +00002688 { "loadvm", HAS_ARG, QEMU_OPTION_loadvm },
2689 { "full-screen", 0, QEMU_OPTION_full_screen },
bellard82c643f2004-07-14 17:28:13 +00002690
bellard1f042752004-06-05 13:46:47 +00002691 /* temporary options */
2692 { "pci", 0, QEMU_OPTION_pci },
2693 { "cirrusvga", 0, QEMU_OPTION_cirrusvga },
bellardcd6f1162004-05-13 22:02:20 +00002694 { NULL },
bellardfc01f7e2003-06-30 10:03:06 +00002695};
2696
bellard77fef8c2004-02-16 22:05:46 +00002697#if defined (TARGET_I386) && defined(USE_CODE_COPY)
2698
2699/* this stack is only used during signal handling */
2700#define SIGNAL_STACK_SIZE 32768
2701
2702static uint8_t *signal_stack;
2703
2704#endif
2705
bellard5905b2e2004-08-01 21:53:26 +00002706/* password input */
2707
2708static BlockDriverState *get_bdrv(int index)
2709{
2710 BlockDriverState *bs;
2711
2712 if (index < 4) {
2713 bs = bs_table[index];
2714 } else if (index < 6) {
2715 bs = fd_table[index - 4];
2716 } else {
2717 bs = NULL;
2718 }
2719 return bs;
2720}
2721
2722static void read_passwords(void)
2723{
2724 BlockDriverState *bs;
2725 int i, j;
2726 char password[256];
2727
2728 for(i = 0; i < 6; i++) {
2729 bs = get_bdrv(i);
2730 if (bs && bdrv_is_encrypted(bs)) {
2731 term_printf("%s is encrypted.\n", bdrv_get_device_name(bs));
2732 for(j = 0; j < 3; j++) {
2733 monitor_readline("Password: ",
2734 1, password, sizeof(password));
2735 if (bdrv_set_key(bs, password) == 0)
2736 break;
2737 term_printf("invalid password\n");
2738 }
2739 }
2740 }
2741}
2742
bellardc20709a2004-04-21 23:27:19 +00002743#define NET_IF_TUN 0
2744#define NET_IF_USER 1
2745#define NET_IF_DUMMY 2
2746
bellard0824d6f2003-06-24 13:42:40 +00002747int main(int argc, char **argv)
2748{
bellard67b915a2004-03-31 23:37:16 +00002749#ifdef CONFIG_GDBSTUB
2750 int use_gdbstub, gdbstub_port;
2751#endif
bellardcd6f1162004-05-13 22:02:20 +00002752 int i, has_cdrom;
bellard1ccde1c2004-02-06 19:46:14 +00002753 int snapshot, linux_boot;
bellardc45886d2004-01-05 00:02:06 +00002754 CPUState *env;
bellard7f7f9872003-10-30 01:11:23 +00002755 const char *initrd_filename;
bellardc45886d2004-01-05 00:02:06 +00002756 const char *hd_filename[MAX_DISKS], *fd_filename[MAX_FD];
bellarda20dd502003-09-30 21:07:02 +00002757 const char *kernel_filename, *kernel_cmdline;
bellard313aa562003-08-10 21:52:11 +00002758 DisplayState *ds = &display_state;
bellardc4b1fcc2004-03-14 21:44:30 +00002759 int cyls, heads, secs;
bellarda541f292004-04-12 20:39:29 +00002760 int start_emulation = 1;
bellard702c6512004-04-02 21:21:32 +00002761 uint8_t macaddr[6];
bellardc20709a2004-04-21 23:27:19 +00002762 int net_if_type, nb_tun_fds, tun_fds[MAX_NICS];
bellardcd6f1162004-05-13 22:02:20 +00002763 int optind;
2764 const char *r, *optarg;
bellard82c643f2004-07-14 17:28:13 +00002765 CharDriverState *monitor_hd;
2766 char monitor_device[128];
bellard8d11df92004-08-24 21:13:40 +00002767 char serial_devices[MAX_SERIAL_PORTS][128];
2768 int serial_device_index;
bellardd63d3072004-10-03 13:29:03 +00002769 const char *loadvm = NULL;
bellard8d11df92004-08-24 21:13:40 +00002770
bellard67b915a2004-03-31 23:37:16 +00002771#if !defined(CONFIG_SOFTMMU)
bellard0824d6f2003-06-24 13:42:40 +00002772 /* we never want that malloc() uses mmap() */
2773 mallopt(M_MMAP_THRESHOLD, 4096 * 1024);
bellard67b915a2004-03-31 23:37:16 +00002774#endif
bellardfc01f7e2003-06-30 10:03:06 +00002775 initrd_filename = NULL;
bellardc45886d2004-01-05 00:02:06 +00002776 for(i = 0; i < MAX_FD; i++)
2777 fd_filename[i] = NULL;
bellardfc01f7e2003-06-30 10:03:06 +00002778 for(i = 0; i < MAX_DISKS; i++)
2779 hd_filename[i] = NULL;
bellarda00bad72004-05-22 21:39:06 +00002780 ram_size = DEFAULT_RAM_SIZE * 1024 * 1024;
bellard313aa562003-08-10 21:52:11 +00002781 vga_ram_size = VGA_RAM_SIZE;
bellard0ced6582004-05-23 21:06:12 +00002782 bios_size = BIOS_SIZE;
bellardf1510b22003-06-25 00:07:40 +00002783 pstrcpy(network_script, sizeof(network_script), DEFAULT_NETWORK_SCRIPT);
bellard67b915a2004-03-31 23:37:16 +00002784#ifdef CONFIG_GDBSTUB
bellardb4608c02003-06-27 17:34:32 +00002785 use_gdbstub = 0;
2786 gdbstub_port = DEFAULT_GDBSTUB_PORT;
bellard67b915a2004-03-31 23:37:16 +00002787#endif
bellard33e39632003-07-06 17:15:21 +00002788 snapshot = 0;
bellarda20dd502003-09-30 21:07:02 +00002789 nographic = 0;
2790 kernel_filename = NULL;
2791 kernel_cmdline = "";
bellardc4b1fcc2004-03-14 21:44:30 +00002792 has_cdrom = 1;
2793 cyls = heads = secs = 0;
bellard82c643f2004-07-14 17:28:13 +00002794 pstrcpy(monitor_device, sizeof(monitor_device), "vc");
bellardc4b1fcc2004-03-14 21:44:30 +00002795
bellard8d11df92004-08-24 21:13:40 +00002796 pstrcpy(serial_devices[0], sizeof(serial_devices[0]), "vc");
2797 for(i = 1; i < MAX_SERIAL_PORTS; i++)
2798 serial_devices[i][0] = '\0';
2799 serial_device_index = 0;
2800
bellardc20709a2004-04-21 23:27:19 +00002801 nb_tun_fds = 0;
2802 net_if_type = -1;
bellardc4b1fcc2004-03-14 21:44:30 +00002803 nb_nics = 1;
bellard702c6512004-04-02 21:21:32 +00002804 /* default mac address of the first network interface */
2805 macaddr[0] = 0x52;
2806 macaddr[1] = 0x54;
2807 macaddr[2] = 0x00;
2808 macaddr[3] = 0x12;
2809 macaddr[4] = 0x34;
2810 macaddr[5] = 0x56;
bellard82c643f2004-07-14 17:28:13 +00002811
bellardcd6f1162004-05-13 22:02:20 +00002812 optind = 1;
bellard0824d6f2003-06-24 13:42:40 +00002813 for(;;) {
bellardcd6f1162004-05-13 22:02:20 +00002814 if (optind >= argc)
bellard0824d6f2003-06-24 13:42:40 +00002815 break;
bellardcd6f1162004-05-13 22:02:20 +00002816 r = argv[optind];
2817 if (r[0] != '-') {
2818 hd_filename[0] = argv[optind++];
2819 } else {
2820 const QEMUOption *popt;
2821
2822 optind++;
2823 popt = qemu_options;
2824 for(;;) {
2825 if (!popt->name) {
2826 fprintf(stderr, "%s: invalid option -- '%s'\n",
2827 argv[0], r);
2828 exit(1);
2829 }
2830 if (!strcmp(popt->name, r + 1))
2831 break;
2832 popt++;
2833 }
2834 if (popt->flags & HAS_ARG) {
2835 if (optind >= argc) {
2836 fprintf(stderr, "%s: option '%s' requires an argument\n",
2837 argv[0], r);
2838 exit(1);
2839 }
2840 optarg = argv[optind++];
2841 } else {
2842 optarg = NULL;
2843 }
2844
2845 switch(popt->index) {
2846 case QEMU_OPTION_initrd:
bellardfc01f7e2003-06-30 10:03:06 +00002847 initrd_filename = optarg;
2848 break;
bellardcd6f1162004-05-13 22:02:20 +00002849 case QEMU_OPTION_hda:
bellardfc01f7e2003-06-30 10:03:06 +00002850 hd_filename[0] = optarg;
2851 break;
bellardcd6f1162004-05-13 22:02:20 +00002852 case QEMU_OPTION_hdb:
bellardfc01f7e2003-06-30 10:03:06 +00002853 hd_filename[1] = optarg;
2854 break;
bellardcd6f1162004-05-13 22:02:20 +00002855 case QEMU_OPTION_snapshot:
bellard33e39632003-07-06 17:15:21 +00002856 snapshot = 1;
2857 break;
bellardcd6f1162004-05-13 22:02:20 +00002858 case QEMU_OPTION_hdachs:
bellard330d0412003-07-26 18:11:40 +00002859 {
bellard330d0412003-07-26 18:11:40 +00002860 const char *p;
2861 p = optarg;
2862 cyls = strtol(p, (char **)&p, 0);
2863 if (*p != ',')
2864 goto chs_fail;
2865 p++;
2866 heads = strtol(p, (char **)&p, 0);
2867 if (*p != ',')
2868 goto chs_fail;
2869 p++;
2870 secs = strtol(p, (char **)&p, 0);
bellardc4b1fcc2004-03-14 21:44:30 +00002871 if (*p != '\0') {
2872 chs_fail:
2873 cyls = 0;
2874 }
bellard330d0412003-07-26 18:11:40 +00002875 }
2876 break;
bellardcd6f1162004-05-13 22:02:20 +00002877 case QEMU_OPTION_nographic:
bellard82c643f2004-07-14 17:28:13 +00002878 pstrcpy(monitor_device, sizeof(monitor_device), "stdio");
bellard8d11df92004-08-24 21:13:40 +00002879 pstrcpy(serial_devices[0], sizeof(serial_devices[0]), "stdio");
bellarda20dd502003-09-30 21:07:02 +00002880 nographic = 1;
2881 break;
bellardcd6f1162004-05-13 22:02:20 +00002882 case QEMU_OPTION_kernel:
bellarda20dd502003-09-30 21:07:02 +00002883 kernel_filename = optarg;
2884 break;
bellardcd6f1162004-05-13 22:02:20 +00002885 case QEMU_OPTION_append:
bellarda20dd502003-09-30 21:07:02 +00002886 kernel_cmdline = optarg;
bellard313aa562003-08-10 21:52:11 +00002887 break;
bellardcd6f1162004-05-13 22:02:20 +00002888 case QEMU_OPTION_tun_fd:
bellardc4b1fcc2004-03-14 21:44:30 +00002889 {
2890 const char *p;
2891 int fd;
bellardd6b86f42004-05-12 19:59:20 +00002892 net_if_type = NET_IF_TUN;
bellardc20709a2004-04-21 23:27:19 +00002893 if (nb_tun_fds < MAX_NICS) {
2894 fd = strtol(optarg, (char **)&p, 0);
2895 if (*p != '\0') {
2896 fprintf(stderr, "qemu: invalid fd for network interface %d\n", nb_tun_fds);
bellardc4b1fcc2004-03-14 21:44:30 +00002897 exit(1);
2898 }
bellardc20709a2004-04-21 23:27:19 +00002899 tun_fds[nb_tun_fds++] = fd;
bellardc4b1fcc2004-03-14 21:44:30 +00002900 }
2901 }
bellard42f1e0e2003-09-30 22:11:17 +00002902 break;
bellardcd6f1162004-05-13 22:02:20 +00002903 case QEMU_OPTION_hdc:
bellard36b486b2003-11-11 13:36:08 +00002904 hd_filename[2] = optarg;
bellardc4b1fcc2004-03-14 21:44:30 +00002905 has_cdrom = 0;
bellard36b486b2003-11-11 13:36:08 +00002906 break;
bellardcd6f1162004-05-13 22:02:20 +00002907 case QEMU_OPTION_hdd:
bellard36b486b2003-11-11 13:36:08 +00002908 hd_filename[3] = optarg;
2909 break;
bellardcd6f1162004-05-13 22:02:20 +00002910 case QEMU_OPTION_cdrom:
bellard36b486b2003-11-11 13:36:08 +00002911 hd_filename[2] = optarg;
bellardc4b1fcc2004-03-14 21:44:30 +00002912 has_cdrom = 1;
bellard36b486b2003-11-11 13:36:08 +00002913 break;
bellardcd6f1162004-05-13 22:02:20 +00002914 case QEMU_OPTION_boot:
bellard36b486b2003-11-11 13:36:08 +00002915 boot_device = optarg[0];
bellardc45886d2004-01-05 00:02:06 +00002916 if (boot_device != 'a' && boot_device != 'b' &&
2917 boot_device != 'c' && boot_device != 'd') {
bellard36b486b2003-11-11 13:36:08 +00002918 fprintf(stderr, "qemu: invalid boot device '%c'\n", boot_device);
2919 exit(1);
2920 }
2921 break;
bellardcd6f1162004-05-13 22:02:20 +00002922 case QEMU_OPTION_fda:
bellardc45886d2004-01-05 00:02:06 +00002923 fd_filename[0] = optarg;
2924 break;
bellardcd6f1162004-05-13 22:02:20 +00002925 case QEMU_OPTION_fdb:
bellardc45886d2004-01-05 00:02:06 +00002926 fd_filename[1] = optarg;
2927 break;
bellardcd6f1162004-05-13 22:02:20 +00002928 case QEMU_OPTION_no_code_copy:
bellard77fef8c2004-02-16 22:05:46 +00002929 code_copy_enabled = 0;
2930 break;
bellardcd6f1162004-05-13 22:02:20 +00002931 case QEMU_OPTION_nics:
bellardc4b1fcc2004-03-14 21:44:30 +00002932 nb_nics = atoi(optarg);
bellard3a1bc172004-05-12 19:54:43 +00002933 if (nb_nics < 0 || nb_nics > MAX_NICS) {
bellardc4b1fcc2004-03-14 21:44:30 +00002934 fprintf(stderr, "qemu: invalid number of network interfaces\n");
2935 exit(1);
2936 }
2937 break;
bellardcd6f1162004-05-13 22:02:20 +00002938 case QEMU_OPTION_macaddr:
bellard702c6512004-04-02 21:21:32 +00002939 {
2940 const char *p;
2941 int i;
2942 p = optarg;
2943 for(i = 0; i < 6; i++) {
2944 macaddr[i] = strtol(p, (char **)&p, 16);
2945 if (i == 5) {
2946 if (*p != '\0')
2947 goto macaddr_error;
2948 } else {
2949 if (*p != ':') {
2950 macaddr_error:
2951 fprintf(stderr, "qemu: invalid syntax for ethernet address\n");
2952 exit(1);
2953 }
2954 p++;
2955 }
2956 }
2957 }
2958 break;
bellardc7f74642004-08-24 21:57:12 +00002959#ifdef CONFIG_SLIRP
2960 case QEMU_OPTION_tftp:
bellardc7f74642004-08-24 21:57:12 +00002961 tftp_prefix = optarg;
bellard9bf05442004-08-25 22:12:49 +00002962 break;
bellardc94c8d62004-09-13 21:37:34 +00002963#ifndef _WIN32
bellard9d728e82004-09-05 23:09:03 +00002964 case QEMU_OPTION_smb:
2965 net_slirp_smb(optarg);
2966 break;
bellardc94c8d62004-09-13 21:37:34 +00002967#endif
bellardcd6f1162004-05-13 22:02:20 +00002968 case QEMU_OPTION_user_net:
bellardc20709a2004-04-21 23:27:19 +00002969 net_if_type = NET_IF_USER;
2970 break;
bellard9bf05442004-08-25 22:12:49 +00002971 case QEMU_OPTION_redir:
2972 net_slirp_redir(optarg);
2973 break;
bellardc7f74642004-08-24 21:57:12 +00002974#endif
bellardcd6f1162004-05-13 22:02:20 +00002975 case QEMU_OPTION_dummy_net:
bellardc20709a2004-04-21 23:27:19 +00002976 net_if_type = NET_IF_DUMMY;
2977 break;
bellardcd6f1162004-05-13 22:02:20 +00002978 case QEMU_OPTION_enable_audio:
bellardaaaa7df2004-04-26 20:56:53 +00002979 audio_enabled = 1;
2980 break;
bellardcd6f1162004-05-13 22:02:20 +00002981 case QEMU_OPTION_h:
bellard0824d6f2003-06-24 13:42:40 +00002982 help();
bellardcd6f1162004-05-13 22:02:20 +00002983 break;
2984 case QEMU_OPTION_m:
2985 ram_size = atoi(optarg) * 1024 * 1024;
2986 if (ram_size <= 0)
2987 help();
2988 if (ram_size > PHYS_RAM_MAX_SIZE) {
2989 fprintf(stderr, "qemu: at most %d MB RAM can be simulated\n",
2990 PHYS_RAM_MAX_SIZE / (1024 * 1024));
2991 exit(1);
2992 }
2993 break;
2994 case QEMU_OPTION_d:
2995 {
2996 int mask;
2997 CPULogItem *item;
2998
2999 mask = cpu_str_to_log_mask(optarg);
3000 if (!mask) {
3001 printf("Log items (comma separated):\n");
bellardf193c792004-03-21 17:06:25 +00003002 for(item = cpu_log_items; item->mask != 0; item++) {
3003 printf("%-10s %s\n", item->name, item->help);
3004 }
3005 exit(1);
bellardcd6f1162004-05-13 22:02:20 +00003006 }
3007 cpu_set_log(mask);
bellardf193c792004-03-21 17:06:25 +00003008 }
bellardcd6f1162004-05-13 22:02:20 +00003009 break;
3010 case QEMU_OPTION_n:
3011 pstrcpy(network_script, sizeof(network_script), optarg);
3012 break;
bellard67b915a2004-03-31 23:37:16 +00003013#ifdef CONFIG_GDBSTUB
bellardcd6f1162004-05-13 22:02:20 +00003014 case QEMU_OPTION_s:
3015 use_gdbstub = 1;
3016 break;
3017 case QEMU_OPTION_p:
3018 gdbstub_port = atoi(optarg);
3019 break;
bellard67b915a2004-03-31 23:37:16 +00003020#endif
bellardcd6f1162004-05-13 22:02:20 +00003021 case QEMU_OPTION_L:
3022 bios_dir = optarg;
3023 break;
3024 case QEMU_OPTION_S:
3025 start_emulation = 0;
3026 break;
bellard69b91032004-05-18 23:05:28 +00003027 case QEMU_OPTION_pci:
3028 pci_enabled = 1;
3029 break;
bellardbb0c6722004-06-20 12:37:32 +00003030 case QEMU_OPTION_isa:
3031 pci_enabled = 0;
3032 break;
bellard77d4bc32004-05-26 22:13:53 +00003033 case QEMU_OPTION_prep:
3034 prep_enabled = 1;
3035 break;
bellardee22c2f2004-06-03 12:49:50 +00003036 case QEMU_OPTION_localtime:
3037 rtc_utc = 0;
3038 break;
bellard1f042752004-06-05 13:46:47 +00003039 case QEMU_OPTION_cirrusvga:
3040 cirrus_vga_enabled = 1;
3041 break;
bellard1bfe8562004-07-08 21:17:50 +00003042 case QEMU_OPTION_std_vga:
3043 cirrus_vga_enabled = 0;
3044 break;
bellarde9b137c2004-06-21 16:46:10 +00003045 case QEMU_OPTION_g:
3046 {
3047 const char *p;
3048 int w, h, depth;
3049 p = optarg;
3050 w = strtol(p, (char **)&p, 10);
3051 if (w <= 0) {
3052 graphic_error:
3053 fprintf(stderr, "qemu: invalid resolution or depth\n");
3054 exit(1);
3055 }
3056 if (*p != 'x')
3057 goto graphic_error;
3058 p++;
3059 h = strtol(p, (char **)&p, 10);
3060 if (h <= 0)
3061 goto graphic_error;
3062 if (*p == 'x') {
3063 p++;
3064 depth = strtol(p, (char **)&p, 10);
3065 if (depth != 8 && depth != 15 && depth != 16 &&
3066 depth != 24 && depth != 32)
3067 goto graphic_error;
3068 } else if (*p == '\0') {
3069 depth = graphic_depth;
3070 } else {
3071 goto graphic_error;
3072 }
3073
3074 graphic_width = w;
3075 graphic_height = h;
3076 graphic_depth = depth;
3077 }
3078 break;
bellard82c643f2004-07-14 17:28:13 +00003079 case QEMU_OPTION_monitor:
3080 pstrcpy(monitor_device, sizeof(monitor_device), optarg);
3081 break;
3082 case QEMU_OPTION_serial:
bellard8d11df92004-08-24 21:13:40 +00003083 if (serial_device_index >= MAX_SERIAL_PORTS) {
3084 fprintf(stderr, "qemu: too many serial ports\n");
3085 exit(1);
3086 }
3087 pstrcpy(serial_devices[serial_device_index],
3088 sizeof(serial_devices[0]), optarg);
3089 serial_device_index++;
bellard82c643f2004-07-14 17:28:13 +00003090 break;
bellardd63d3072004-10-03 13:29:03 +00003091 case QEMU_OPTION_loadvm:
3092 loadvm = optarg;
3093 break;
3094 case QEMU_OPTION_full_screen:
3095 full_screen = 1;
3096 break;
bellardcd6f1162004-05-13 22:02:20 +00003097 }
bellard0824d6f2003-06-24 13:42:40 +00003098 }
3099 }
bellard330d0412003-07-26 18:11:40 +00003100
bellarda20dd502003-09-30 21:07:02 +00003101 linux_boot = (kernel_filename != NULL);
bellard330d0412003-07-26 18:11:40 +00003102
bellardc45886d2004-01-05 00:02:06 +00003103 if (!linux_boot && hd_filename[0] == '\0' && hd_filename[2] == '\0' &&
3104 fd_filename[0] == '\0')
bellard0824d6f2003-06-24 13:42:40 +00003105 help();
bellard8f2b1fb2003-11-16 19:46:01 +00003106
3107 /* boot to cd by default if no hard disk */
bellardd0309312004-01-18 22:35:25 +00003108 if (hd_filename[0] == '\0' && boot_device == 'c') {
3109 if (fd_filename[0] != '\0')
3110 boot_device = 'a';
3111 else
3112 boot_device = 'd';
3113 }
bellard0824d6f2003-06-24 13:42:40 +00003114
bellarddc887a42004-01-04 18:18:57 +00003115#if !defined(CONFIG_SOFTMMU)
3116 /* must avoid mmap() usage of glibc by setting a buffer "by hand" */
3117 {
3118 static uint8_t stdout_buf[4096];
3119 setvbuf(stdout, stdout_buf, _IOLBF, sizeof(stdout_buf));
3120 }
3121#else
bellardb118d612003-06-30 23:36:21 +00003122 setvbuf(stdout, NULL, _IOLBF, 0);
bellarddc887a42004-01-04 18:18:57 +00003123#endif
bellard0824d6f2003-06-24 13:42:40 +00003124
bellardc4b1fcc2004-03-14 21:44:30 +00003125 /* init host network redirectors */
bellardc20709a2004-04-21 23:27:19 +00003126 if (net_if_type == -1) {
3127 net_if_type = NET_IF_TUN;
3128#if defined(CONFIG_SLIRP)
3129 if (access(network_script, R_OK) < 0) {
3130 net_if_type = NET_IF_USER;
3131 }
3132#endif
3133 }
3134
3135 for(i = 0; i < nb_nics; i++) {
bellard702c6512004-04-02 21:21:32 +00003136 NetDriverState *nd = &nd_table[i];
bellardc20709a2004-04-21 23:27:19 +00003137 nd->index = i;
bellard702c6512004-04-02 21:21:32 +00003138 /* init virtual mac address */
3139 nd->macaddr[0] = macaddr[0];
3140 nd->macaddr[1] = macaddr[1];
3141 nd->macaddr[2] = macaddr[2];
3142 nd->macaddr[3] = macaddr[3];
3143 nd->macaddr[4] = macaddr[4];
3144 nd->macaddr[5] = macaddr[5] + i;
bellardc20709a2004-04-21 23:27:19 +00003145 switch(net_if_type) {
3146#if defined(CONFIG_SLIRP)
3147 case NET_IF_USER:
3148 net_slirp_init(nd);
3149 break;
3150#endif
3151#if !defined(_WIN32)
3152 case NET_IF_TUN:
3153 if (i < nb_tun_fds) {
3154 net_fd_init(nd, tun_fds[i]);
3155 } else {
bellardd9276372004-04-26 19:44:57 +00003156 if (net_tun_init(nd) < 0)
3157 net_dummy_init(nd);
bellardc20709a2004-04-21 23:27:19 +00003158 }
3159 break;
3160#endif
3161 case NET_IF_DUMMY:
3162 default:
3163 net_dummy_init(nd);
3164 break;
3165 }
bellard702c6512004-04-02 21:21:32 +00003166 }
bellardf1510b22003-06-25 00:07:40 +00003167
bellard0824d6f2003-06-24 13:42:40 +00003168 /* init the memory */
bellard0ced6582004-05-23 21:06:12 +00003169 phys_ram_size = ram_size + vga_ram_size + bios_size;
bellard7f7f9872003-10-30 01:11:23 +00003170
3171#ifdef CONFIG_SOFTMMU
bellard7d3505c2004-05-12 19:32:15 +00003172#ifdef _BSD
bellard83fb7ad2004-07-05 21:25:26 +00003173 /* mallocs are always aligned on BSD. valloc is better for correctness */
3174 phys_ram_base = valloc(phys_ram_size);
bellard7d3505c2004-05-12 19:32:15 +00003175#else
bellard1ccde1c2004-02-06 19:46:14 +00003176 phys_ram_base = memalign(TARGET_PAGE_SIZE, phys_ram_size);
bellard7d3505c2004-05-12 19:32:15 +00003177#endif
bellard7f7f9872003-10-30 01:11:23 +00003178 if (!phys_ram_base) {
3179 fprintf(stderr, "Could not allocate physical memory\n");
bellard0824d6f2003-06-24 13:42:40 +00003180 exit(1);
3181 }
bellard7f7f9872003-10-30 01:11:23 +00003182#else
3183 /* as we must map the same page at several addresses, we must use
3184 a fd */
3185 {
3186 const char *tmpdir;
3187
3188 tmpdir = getenv("QEMU_TMPDIR");
3189 if (!tmpdir)
3190 tmpdir = "/tmp";
3191 snprintf(phys_ram_file, sizeof(phys_ram_file), "%s/vlXXXXXX", tmpdir);
3192 if (mkstemp(phys_ram_file) < 0) {
3193 fprintf(stderr, "Could not create temporary memory file '%s'\n",
3194 phys_ram_file);
3195 exit(1);
3196 }
3197 phys_ram_fd = open(phys_ram_file, O_CREAT | O_TRUNC | O_RDWR, 0600);
3198 if (phys_ram_fd < 0) {
3199 fprintf(stderr, "Could not open temporary memory file '%s'\n",
3200 phys_ram_file);
3201 exit(1);
3202 }
bellard1ccde1c2004-02-06 19:46:14 +00003203 ftruncate(phys_ram_fd, phys_ram_size);
bellard7f7f9872003-10-30 01:11:23 +00003204 unlink(phys_ram_file);
bellard1ccde1c2004-02-06 19:46:14 +00003205 phys_ram_base = mmap(get_mmap_addr(phys_ram_size),
3206 phys_ram_size,
bellard7f7f9872003-10-30 01:11:23 +00003207 PROT_WRITE | PROT_READ, MAP_SHARED | MAP_FIXED,
3208 phys_ram_fd, 0);
3209 if (phys_ram_base == MAP_FAILED) {
3210 fprintf(stderr, "Could not map physical memory\n");
3211 exit(1);
3212 }
3213 }
3214#endif
bellard0824d6f2003-06-24 13:42:40 +00003215
bellardc4b1fcc2004-03-14 21:44:30 +00003216 /* we always create the cdrom drive, even if no disk is there */
bellard5905b2e2004-08-01 21:53:26 +00003217 bdrv_init();
bellardc4b1fcc2004-03-14 21:44:30 +00003218 if (has_cdrom) {
3219 bs_table[2] = bdrv_new("cdrom");
3220 bdrv_set_type_hint(bs_table[2], BDRV_TYPE_CDROM);
3221 }
3222
bellard33e39632003-07-06 17:15:21 +00003223 /* open the virtual block devices */
3224 for(i = 0; i < MAX_DISKS; i++) {
3225 if (hd_filename[i]) {
bellard33e39632003-07-06 17:15:21 +00003226 if (!bs_table[i]) {
bellardc4b1fcc2004-03-14 21:44:30 +00003227 char buf[64];
3228 snprintf(buf, sizeof(buf), "hd%c", i + 'a');
3229 bs_table[i] = bdrv_new(buf);
3230 }
3231 if (bdrv_open(bs_table[i], hd_filename[i], snapshot) < 0) {
bellard5905b2e2004-08-01 21:53:26 +00003232 fprintf(stderr, "qemu: could not open hard disk image '%s'\n",
bellard33e39632003-07-06 17:15:21 +00003233 hd_filename[i]);
3234 exit(1);
3235 }
bellardc4b1fcc2004-03-14 21:44:30 +00003236 if (i == 0 && cyls != 0)
3237 bdrv_set_geometry_hint(bs_table[i], cyls, heads, secs);
3238 }
3239 }
3240
3241 /* we always create at least one floppy disk */
3242 fd_table[0] = bdrv_new("fda");
3243 bdrv_set_type_hint(fd_table[0], BDRV_TYPE_FLOPPY);
3244
3245 for(i = 0; i < MAX_FD; i++) {
3246 if (fd_filename[i]) {
3247 if (!fd_table[i]) {
3248 char buf[64];
3249 snprintf(buf, sizeof(buf), "fd%c", i + 'a');
3250 fd_table[i] = bdrv_new(buf);
3251 bdrv_set_type_hint(fd_table[i], BDRV_TYPE_FLOPPY);
3252 }
3253 if (fd_filename[i] != '\0') {
3254 if (bdrv_open(fd_table[i], fd_filename[i], snapshot) < 0) {
bellardc20709a2004-04-21 23:27:19 +00003255 fprintf(stderr, "qemu: could not open floppy disk image '%s'\n",
bellardc4b1fcc2004-03-14 21:44:30 +00003256 fd_filename[i]);
3257 exit(1);
3258 }
3259 }
bellard33e39632003-07-06 17:15:21 +00003260 }
3261 }
3262
bellard330d0412003-07-26 18:11:40 +00003263 /* init CPU state */
3264 env = cpu_init();
3265 global_env = env;
3266 cpu_single_env = env;
bellard0824d6f2003-06-24 13:42:40 +00003267
bellard8a7ddc32004-03-31 19:00:16 +00003268 register_savevm("timer", 0, 1, timer_save, timer_load, env);
bellard02ba45c2004-06-25 14:46:23 +00003269 register_savevm("cpu", 0, 2, cpu_save, cpu_load, env);
bellard8a7ddc32004-03-31 19:00:16 +00003270 register_savevm("ram", 0, 1, ram_save, ram_load, NULL);
bellardbb0c6722004-06-20 12:37:32 +00003271 qemu_register_reset(main_cpu_reset, global_env);
bellard8a7ddc32004-03-31 19:00:16 +00003272
bellard330d0412003-07-26 18:11:40 +00003273 init_ioports();
bellard80cabfa2004-03-14 12:20:30 +00003274 cpu_calibrate_ticks();
bellard0824d6f2003-06-24 13:42:40 +00003275
bellard313aa562003-08-10 21:52:11 +00003276 /* terminal init */
bellarda20dd502003-09-30 21:07:02 +00003277 if (nographic) {
bellard313aa562003-08-10 21:52:11 +00003278 dumb_display_init(ds);
3279 } else {
3280#ifdef CONFIG_SDL
bellardd63d3072004-10-03 13:29:03 +00003281 sdl_display_init(ds, full_screen);
bellard313aa562003-08-10 21:52:11 +00003282#else
3283 dumb_display_init(ds);
3284#endif
3285 }
bellard0824d6f2003-06-24 13:42:40 +00003286
bellard82c643f2004-07-14 17:28:13 +00003287 vga_console = graphic_console_init(ds);
3288
3289 monitor_hd = qemu_chr_open(monitor_device);
3290 if (!monitor_hd) {
3291 fprintf(stderr, "qemu: could not open monitor device '%s'\n", monitor_device);
3292 exit(1);
3293 }
3294 monitor_init(monitor_hd, !nographic);
3295
bellard8d11df92004-08-24 21:13:40 +00003296 for(i = 0; i < MAX_SERIAL_PORTS; i++) {
3297 if (serial_devices[i][0] != '\0') {
3298 serial_hds[i] = qemu_chr_open(serial_devices[i]);
3299 if (!serial_hds[i]) {
3300 fprintf(stderr, "qemu: could not open serial device '%s'\n",
3301 serial_devices[i]);
3302 exit(1);
3303 }
3304 if (!strcmp(serial_devices[i], "vc"))
3305 qemu_chr_printf(serial_hds[i], "serial%d console\n", i);
3306 }
bellard82c643f2004-07-14 17:28:13 +00003307 }
bellard82c643f2004-07-14 17:28:13 +00003308
bellard0824d6f2003-06-24 13:42:40 +00003309 /* setup cpu signal handlers for MMU / self modifying code handling */
bellard77fef8c2004-02-16 22:05:46 +00003310#if !defined(CONFIG_SOFTMMU)
bellard8a7ddc32004-03-31 19:00:16 +00003311
bellard77fef8c2004-02-16 22:05:46 +00003312#if defined (TARGET_I386) && defined(USE_CODE_COPY)
3313 {
3314 stack_t stk;
bellard73332e52004-04-04 20:22:28 +00003315 signal_stack = memalign(16, SIGNAL_STACK_SIZE);
bellard77fef8c2004-02-16 22:05:46 +00003316 stk.ss_sp = signal_stack;
3317 stk.ss_size = SIGNAL_STACK_SIZE;
3318 stk.ss_flags = 0;
3319
3320 if (sigaltstack(&stk, NULL) < 0) {
3321 perror("sigaltstack");
3322 exit(1);
3323 }
3324 }
3325#endif
bellard8a7ddc32004-03-31 19:00:16 +00003326 {
3327 struct sigaction act;
bellard77fef8c2004-02-16 22:05:46 +00003328
bellard8a7ddc32004-03-31 19:00:16 +00003329 sigfillset(&act.sa_mask);
3330 act.sa_flags = SA_SIGINFO;
bellard77fef8c2004-02-16 22:05:46 +00003331#if defined (TARGET_I386) && defined(USE_CODE_COPY)
bellard8a7ddc32004-03-31 19:00:16 +00003332 act.sa_flags |= SA_ONSTACK;
bellard77fef8c2004-02-16 22:05:46 +00003333#endif
bellard8a7ddc32004-03-31 19:00:16 +00003334 act.sa_sigaction = host_segv_handler;
3335 sigaction(SIGSEGV, &act, NULL);
3336 sigaction(SIGBUS, &act, NULL);
bellard77fef8c2004-02-16 22:05:46 +00003337#if defined (TARGET_I386) && defined(USE_CODE_COPY)
bellard8a7ddc32004-03-31 19:00:16 +00003338 sigaction(SIGFPE, &act, NULL);
bellard77fef8c2004-02-16 22:05:46 +00003339#endif
bellard8a7ddc32004-03-31 19:00:16 +00003340 }
bellard3a51dee2003-10-27 21:18:35 +00003341#endif
bellard0824d6f2003-06-24 13:42:40 +00003342
bellard67b915a2004-03-31 23:37:16 +00003343#ifndef _WIN32
bellard8a7ddc32004-03-31 19:00:16 +00003344 {
3345 struct sigaction act;
3346 sigfillset(&act.sa_mask);
3347 act.sa_flags = 0;
3348 act.sa_handler = SIG_IGN;
3349 sigaction(SIGPIPE, &act, NULL);
3350 }
bellard67b915a2004-03-31 23:37:16 +00003351#endif
bellard73332e52004-04-04 20:22:28 +00003352 init_timers();
3353
3354#if defined(TARGET_I386)
3355 pc_init(ram_size, vga_ram_size, boot_device,
3356 ds, fd_filename, snapshot,
3357 kernel_filename, kernel_cmdline, initrd_filename);
3358#elif defined(TARGET_PPC)
bellarda541f292004-04-12 20:39:29 +00003359 ppc_init(ram_size, vga_ram_size, boot_device,
3360 ds, fd_filename, snapshot,
3361 kernel_filename, kernel_cmdline, initrd_filename);
bellarde95c8d52004-09-30 22:22:08 +00003362#elif defined(TARGET_SPARC)
3363 sun4m_init(ram_size, vga_ram_size, boot_device,
3364 ds, fd_filename, snapshot,
3365 kernel_filename, kernel_cmdline, initrd_filename);
bellard73332e52004-04-04 20:22:28 +00003366#endif
3367
bellard8a7ddc32004-03-31 19:00:16 +00003368 gui_timer = qemu_new_timer(rt_clock, gui_update, NULL);
3369 qemu_mod_timer(gui_timer, qemu_get_clock(rt_clock));
bellard7f7f9872003-10-30 01:11:23 +00003370
bellard67b915a2004-03-31 23:37:16 +00003371#ifdef CONFIG_GDBSTUB
bellardb4608c02003-06-27 17:34:32 +00003372 if (use_gdbstub) {
bellard8a7ddc32004-03-31 19:00:16 +00003373 if (gdbserver_start(gdbstub_port) < 0) {
3374 fprintf(stderr, "Could not open gdbserver socket on port %d\n",
3375 gdbstub_port);
3376 exit(1);
3377 } else {
3378 printf("Waiting gdb connection on port %d\n", gdbstub_port);
3379 }
bellard67b915a2004-03-31 23:37:16 +00003380 } else
3381#endif
bellardd63d3072004-10-03 13:29:03 +00003382 if (loadvm)
3383 qemu_loadvm(loadvm);
3384
bellard67b915a2004-03-31 23:37:16 +00003385 {
bellard5905b2e2004-08-01 21:53:26 +00003386 /* XXX: simplify init */
3387 read_passwords();
3388 if (start_emulation) {
3389 vm_start();
3390 }
bellard0824d6f2003-06-24 13:42:40 +00003391 }
bellard8a7ddc32004-03-31 19:00:16 +00003392 main_loop();
bellard40c3bac2004-04-04 12:56:28 +00003393 quit_timers();
bellard0824d6f2003-06-24 13:42:40 +00003394 return 0;
3395}