Diff for /qemu/vl.c between versions 1.1.1.3 and 1.1.1.4

version 1.1.1.3, 2018/04/24 16:40:26 version 1.1.1.4, 2018/04/24 16:42:28
Line 92 Line 92
 //#define DEBUG_UNUSED_IOPORT  //#define DEBUG_UNUSED_IOPORT
 //#define DEBUG_IOPORT  //#define DEBUG_IOPORT
   
 #if !defined(CONFIG_SOFTMMU)  
 #define PHYS_RAM_MAX_SIZE (256 * 1024 * 1024)  
 #else  
 #define PHYS_RAM_MAX_SIZE (2047 * 1024 * 1024)  #define PHYS_RAM_MAX_SIZE (2047 * 1024 * 1024)
 #endif  
   
 #ifdef TARGET_PPC  #ifdef TARGET_PPC
 #define DEFAULT_RAM_SIZE 144  #define DEFAULT_RAM_SIZE 144
Line 106 Line 102
 /* in ms */  /* in ms */
 #define GUI_REFRESH_INTERVAL 30  #define GUI_REFRESH_INTERVAL 30
   
   /* Max number of USB devices that can be specified on the commandline.  */
   #define MAX_USB_CMDLINE 8
   
 /* XXX: use a two level table to limit memory usage */  /* XXX: use a two level table to limit memory usage */
 #define MAX_IOPORTS 65536  #define MAX_IOPORTS 65536
   
Line 145  CharDriverState *parallel_hds[MAX_PARALL Line 144  CharDriverState *parallel_hds[MAX_PARALL
 int win2k_install_hack = 0;  int win2k_install_hack = 0;
 #endif  #endif
 int usb_enabled = 0;  int usb_enabled = 0;
 USBPort *vm_usb_ports[MAX_VM_USB_PORTS];  
 USBDevice *vm_usb_hub;  
 static VLANState *first_vlan;  static VLANState *first_vlan;
 int smp_cpus = 1;  int smp_cpus = 1;
 int vnc_display = -1;  int vnc_display = -1;
Line 157  int vnc_display = -1; Line 154  int vnc_display = -1;
 #else  #else
 #define MAX_CPUS 1  #define MAX_CPUS 1
 #endif  #endif
   int acpi_enabled = 1;
   int fd_bootchk = 1;
   
 /***********************************************************/  /***********************************************************/
 /* x86 ISA bus support */  /* x86 ISA bus support */
Line 483  int kbd_mouse_is_absolute(void) Line 482  int kbd_mouse_is_absolute(void)
     return qemu_put_mouse_event_absolute;      return qemu_put_mouse_event_absolute;
 }  }
   
   /* compute with 96 bit intermediate result: (a*b)/c */
   uint64_t muldiv64(uint64_t a, uint32_t b, uint32_t c)
   {
       union {
           uint64_t ll;
           struct {
   #ifdef WORDS_BIGENDIAN
               uint32_t high, low;
   #else
               uint32_t low, high;
   #endif            
           } l;
       } u, res;
       uint64_t rl, rh;
   
       u.ll = a;
       rl = (uint64_t)u.l.low * (uint64_t)b;
       rh = (uint64_t)u.l.high * (uint64_t)b;
       rh += (rl >> 32);
       res.l.high = rh / c;
       res.l.low = (((rh % c) << 32) + (rl & 0xffffffff)) / c;
       return res.ll;
   }
   
 /***********************************************************/  /***********************************************************/
 /* timers */  /* real time host monotonic timer */
   
 #if defined(__powerpc__)  #define QEMU_TIMER_BASE 1000000000LL
   
 static inline uint32_t get_tbl(void)   #ifdef WIN32
 {  
     uint32_t tbl;  
     asm volatile("mftb %0" : "=r" (tbl));  
     return tbl;  
 }  
   
 static inline uint32_t get_tbu(void)   static int64_t clock_freq;
 {  
         uint32_t tbl;  
         asm volatile("mftbu %0" : "=r" (tbl));  
         return tbl;  
 }  
   
 int64_t cpu_get_real_ticks(void)  static void init_get_clock(void)
 {  {
     uint32_t l, h, h1;      LARGE_INTEGER freq;
     /* NOTE: we test if wrapping has occurred */      int ret;
     do {      ret = QueryPerformanceFrequency(&freq);
         h = get_tbu();      if (ret == 0) {
         l = get_tbl();          fprintf(stderr, "Could not calibrate ticks\n");
         h1 = get_tbu();          exit(1);
     } while (h != h1);      }
     return ((int64_t)h << 32) | l;      clock_freq = freq.QuadPart;
 }  }
   
 #elif defined(__i386__)  static int64_t get_clock(void)
   
 int64_t cpu_get_real_ticks(void)  
 {  {
 #ifdef _WIN32  
     LARGE_INTEGER ti;      LARGE_INTEGER ti;
     QueryPerformanceCounter(&ti);      QueryPerformanceCounter(&ti);
     return ti.QuadPart;      return muldiv64(ti.QuadPart, QEMU_TIMER_BASE, clock_freq);
 #else  
     int64_t val;  
     asm volatile ("rdtsc" : "=A" (val));  
     return val;  
 #endif  
 }  }
   
 #elif defined(__x86_64__)  #else
   
 int64_t cpu_get_real_ticks(void)  
 {  
     uint32_t low,high;  
     int64_t val;  
     asm volatile("rdtsc" : "=a" (low), "=d" (high));  
     val = high;  
     val <<= 32;  
     val |= low;  
     return val;  
 }  
   
 #elif defined(__ia64)  static int use_rt_clock;
   
 int64_t cpu_get_real_ticks(void)  static void init_get_clock(void)
 {  {
         int64_t val;      use_rt_clock = 0;
         asm volatile ("mov %0 = ar.itc" : "=r"(val) :: "memory");  #if defined(__linux__)
         return val;      {
           struct timespec ts;
           if (clock_gettime(CLOCK_MONOTONIC, &ts) == 0) {
               use_rt_clock = 1;
           }
       }
   #endif
 }  }
   
 #elif defined(__s390__)  static int64_t get_clock(void)
   
 int64_t cpu_get_real_ticks(void)  
 {  {
     int64_t val;  #if defined(__linux__)
     asm volatile("stck 0(%1)" : "=m" (val) : "a" (&val) : "cc");      if (use_rt_clock) {
     return val;          struct timespec ts;
           clock_gettime(CLOCK_MONOTONIC, &ts);
           return ts.tv_sec * 1000000000LL + ts.tv_nsec;
       } else 
   #endif
       {
           /* XXX: using gettimeofday leads to problems if the date
              changes, so it should be avoided. */
           struct timeval tv;
           gettimeofday(&tv, NULL);
           return tv.tv_sec * 1000000000LL + (tv.tv_usec * 1000);
       }
 }  }
   
 #else  
 #error unsupported CPU  
 #endif  #endif
   
   /***********************************************************/
   /* guest cycle counter */
   
 static int64_t cpu_ticks_prev;  static int64_t cpu_ticks_prev;
 static int64_t cpu_ticks_offset;  static int64_t cpu_ticks_offset;
   static int64_t cpu_clock_offset;
 static int cpu_ticks_enabled;  static int cpu_ticks_enabled;
   
 static inline int64_t cpu_get_ticks(void)  /* return the host CPU cycle counter and handle stop/restart */
   int64_t cpu_get_ticks(void)
 {  {
     if (!cpu_ticks_enabled) {      if (!cpu_ticks_enabled) {
         return cpu_ticks_offset;          return cpu_ticks_offset;
Line 585  static inline int64_t cpu_get_ticks(void Line 597  static inline int64_t cpu_get_ticks(void
     }      }
 }  }
   
   /* return the host CPU monotonic timer and handle stop/restart */
   static int64_t cpu_get_clock(void)
   {
       int64_t ti;
       if (!cpu_ticks_enabled) {
           return cpu_clock_offset;
       } else {
           ti = get_clock();
           return ti + cpu_clock_offset;
       }
   }
   
 /* enable cpu_get_ticks() */  /* enable cpu_get_ticks() */
 void cpu_enable_ticks(void)  void cpu_enable_ticks(void)
 {  {
     if (!cpu_ticks_enabled) {      if (!cpu_ticks_enabled) {
         cpu_ticks_offset -= cpu_get_real_ticks();          cpu_ticks_offset -= cpu_get_real_ticks();
           cpu_clock_offset -= get_clock();
         cpu_ticks_enabled = 1;          cpu_ticks_enabled = 1;
     }      }
 }  }
Line 600  void cpu_disable_ticks(void) Line 625  void cpu_disable_ticks(void)
 {  {
     if (cpu_ticks_enabled) {      if (cpu_ticks_enabled) {
         cpu_ticks_offset = cpu_get_ticks();          cpu_ticks_offset = cpu_get_ticks();
           cpu_clock_offset = cpu_get_clock();
         cpu_ticks_enabled = 0;          cpu_ticks_enabled = 0;
     }      }
 }  }
   
 #ifdef _WIN32  /***********************************************************/
 void cpu_calibrate_ticks(void)  /* timers */
 {   
     LARGE_INTEGER freq;  
     int ret;  
   
     ret = QueryPerformanceFrequency(&freq);  
     if (ret == 0) {  
         fprintf(stderr, "Could not calibrate ticks\n");  
         exit(1);  
     }  
     ticks_per_sec = freq.QuadPart;  
 }  
   
 #else  
 static int64_t get_clock(void)  
 {  
     struct timeval tv;  
     gettimeofday(&tv, NULL);  
     return tv.tv_sec * 1000000LL + tv.tv_usec;  
 }  
   
 void cpu_calibrate_ticks(void)  
 {  
     int64_t usec, ticks;  
   
     usec = get_clock();  
     ticks = cpu_get_real_ticks();  
     usleep(50 * 1000);  
     usec = get_clock() - usec;  
     ticks = cpu_get_real_ticks() - ticks;  
     ticks_per_sec = (ticks * 1000000LL + (usec >> 1)) / usec;  
 }  
 #endif /* !_WIN32 */  
   
 /* compute with 96 bit intermediate result: (a*b)/c */  
 uint64_t muldiv64(uint64_t a, uint32_t b, uint32_t c)  
 {  
     union {  
         uint64_t ll;  
         struct {  
 #ifdef WORDS_BIGENDIAN  
             uint32_t high, low;  
 #else  
             uint32_t low, high;  
 #endif              
         } l;  
     } u, res;  
     uint64_t rl, rh;  
   
     u.ll = a;  
     rl = (uint64_t)u.l.low * (uint64_t)b;  
     rh = (uint64_t)u.l.high * (uint64_t)b;  
     rh += (rl >> 32);  
     res.l.high = rh / c;  
     res.l.low = (((rh % c) << 32) + (rl & 0xffffffff)) / c;  
     return res.ll;  
 }  
   
 #define QEMU_TIMER_REALTIME 0  #define QEMU_TIMER_REALTIME 0
 #define QEMU_TIMER_VIRTUAL  1  #define QEMU_TIMER_VIRTUAL  1
   
Line 801  int64_t qemu_get_clock(QEMUClock *clock) Line 771  int64_t qemu_get_clock(QEMUClock *clock)
 {  {
     switch(clock->type) {      switch(clock->type) {
     case QEMU_TIMER_REALTIME:      case QEMU_TIMER_REALTIME:
 #ifdef _WIN32          return get_clock() / 1000000;
         return GetTickCount();  
 #else  
         {  
             struct tms tp;  
   
             /* Note that using gettimeofday() is not a good solution  
                for timers because its value change when the date is  
                modified. */  
             if (timer_freq == 100) {  
                 return times(&tp) * 10;  
             } else {  
                 return ((int64_t)times(&tp) * 1000) / timer_freq;  
             }  
         }  
 #endif  
     default:      default:
     case QEMU_TIMER_VIRTUAL:      case QEMU_TIMER_VIRTUAL:
         return cpu_get_ticks();          return cpu_get_clock();
     }      }
 }  }
   
   static void init_timers(void)
   {
       init_get_clock();
       ticks_per_sec = QEMU_TIMER_BASE;
       rt_clock = qemu_new_clock(QEMU_TIMER_REALTIME);
       vm_clock = qemu_new_clock(QEMU_TIMER_VIRTUAL);
   }
   
 /* save a timer */  /* save a timer */
 void qemu_put_timer(QEMUFile *f, QEMUTimer *ts)  void qemu_put_timer(QEMUFile *f, QEMUTimer *ts)
 {  {
Line 891  static void host_alarm_handler(int host_ Line 854  static void host_alarm_handler(int host_
                 delta_max = delta;                  delta_max = delta;
             delta_cum += delta;              delta_cum += delta;
             if (++count == DISP_FREQ) {              if (++count == DISP_FREQ) {
                 printf("timer: min=%lld us max=%lld us avg=%lld us avg_freq=%0.3f Hz\n",                  printf("timer: min=%" PRId64 " us max=%" PRId64 " us avg=%" PRId64 " us avg_freq=%0.3f Hz\n",
                        muldiv64(delta_min, 1000000, ticks_per_sec),                         muldiv64(delta_min, 1000000, ticks_per_sec),
                        muldiv64(delta_max, 1000000, ticks_per_sec),                         muldiv64(delta_max, 1000000, ticks_per_sec),
                        muldiv64(delta_cum, 1000000 / DISP_FREQ, ticks_per_sec),                         muldiv64(delta_cum, 1000000 / DISP_FREQ, ticks_per_sec),
Line 964  static int start_rtc_timer(void) Line 927  static int start_rtc_timer(void)
   
 #endif /* !defined(_WIN32) */  #endif /* !defined(_WIN32) */
   
 static void init_timers(void)  static void init_timer_alarm(void)
 {  {
     rt_clock = qemu_new_clock(QEMU_TIMER_REALTIME);  
     vm_clock = qemu_new_clock(QEMU_TIMER_VIRTUAL);  
   
 #ifdef _WIN32  #ifdef _WIN32
     {      {
         int count=0;          int count=0;
Line 993  static void init_timers(void) Line 953  static void init_timers(void)
             perror("failed CreateEvent");              perror("failed CreateEvent");
             exit(1);              exit(1);
         }          }
         ResetEvent(host_alarm);          qemu_add_wait_object(host_alarm, NULL, NULL);
     }      }
     pit_min_timer_count = ((uint64_t)10000 * PIT_FREQ) / 1000000;      pit_min_timer_count = ((uint64_t)10000 * PIT_FREQ) / 1000000;
 #else  #else
Line 1333  CharDriverState *qemu_chr_open_pipe(cons Line 1293  CharDriverState *qemu_chr_open_pipe(cons
   
 static int term_got_escape, client_index;  static int term_got_escape, client_index;
 static uint8_t term_fifo[TERM_FIFO_MAX_SIZE];  static uint8_t term_fifo[TERM_FIFO_MAX_SIZE];
 int term_fifo_size;  static int term_fifo_size;
   static int term_timestamps;
   static int64_t term_timestamps_start;
   
 void term_print_help(void)  void term_print_help(void)
 {  {
Line 1342  void term_print_help(void) Line 1304  void term_print_help(void)
            "C-a x    exit emulator\n"             "C-a x    exit emulator\n"
            "C-a s    save disk data back to file (if -snapshot)\n"             "C-a s    save disk data back to file (if -snapshot)\n"
            "C-a b    send break (magic sysrq)\n"             "C-a b    send break (magic sysrq)\n"
              "C-a t    toggle console timestamps\n"
            "C-a c    switch between console and monitor\n"             "C-a c    switch between console and monitor\n"
            "C-a C-a  send C-a\n"             "C-a C-a  send C-a\n"
            );             );
Line 1388  static void stdio_received_byte(int ch) Line 1351  static void stdio_received_byte(int ch)
                 goto send_char;                  goto send_char;
             }              }
             break;              break;
           case 't':
               term_timestamps = !term_timestamps;
               term_timestamps_start = -1;
               break;
         case TERM_ESCAPE:          case TERM_ESCAPE:
             goto send_char;              goto send_char;
         }          }
Line 1445  static void stdio_read(void *opaque) Line 1412  static void stdio_read(void *opaque)
         stdio_received_byte(buf[0]);          stdio_received_byte(buf[0]);
 }  }
   
   static int stdio_write(CharDriverState *chr, const uint8_t *buf, int len)
   {
       FDCharDriver *s = chr->opaque;
       if (!term_timestamps) {
           return unix_write(s->fd_out, buf, len);
       } else {
           int i;
           char buf1[64];
   
           for(i = 0; i < len; i++) {
               unix_write(s->fd_out, buf + i, 1);
               if (buf[i] == '\n') {
                   int64_t ti;
                   int secs;
   
                   ti = get_clock();
                   if (term_timestamps_start == -1)
                       term_timestamps_start = ti;
                   ti -= term_timestamps_start;
                   secs = ti / 1000000000;
                   snprintf(buf1, sizeof(buf1), 
                            "[%02d:%02d:%02d.%03d] ",
                            secs / 3600,
                            (secs / 60) % 60,
                            secs % 60,
                            (int)((ti / 1000000) % 1000));
                   unix_write(s->fd_out, buf1, strlen(buf1));
               }
           }
           return len;
       }
   }
   
 /* init terminal so that we can grab keys */  /* init terminal so that we can grab keys */
 static struct termios oldtty;  static struct termios oldtty;
 static int old_fd0_flags;  static int old_fd0_flags;
Line 1490  CharDriverState *qemu_chr_open_stdio(voi Line 1490  CharDriverState *qemu_chr_open_stdio(voi
         if (stdio_nb_clients >= STDIO_MAX_CLIENTS)          if (stdio_nb_clients >= STDIO_MAX_CLIENTS)
             return NULL;              return NULL;
         chr = qemu_chr_open_fd(0, 1);          chr = qemu_chr_open_fd(0, 1);
           chr->chr_write = stdio_write;
         if (stdio_nb_clients == 0)          if (stdio_nb_clients == 0)
             qemu_set_fd_handler2(0, stdio_read_poll, stdio_read, NULL, NULL);              qemu_set_fd_handler2(0, stdio_read_poll, stdio_read, NULL, NULL);
         client_index = stdio_nb_clients;          client_index = stdio_nb_clients;
Line 2046  static int win_chr_pipe_init(WinCharStat Line 2047  static int win_chr_pipe_init(WinCharStat
 }  }
   
   
 CharDriverState *qemu_chr_open_win_pipe(const char *filename)  CharDriverState *qemu_chr_open_win_pipe(const char *filename)
 {  {
     CharDriverState *chr;      CharDriverState *chr;
     WinCharState *s;      WinCharState *s;
   
       chr = qemu_mallocz(sizeof(CharDriverState));
       if (!chr)
           return NULL;
       s = qemu_mallocz(sizeof(WinCharState));
       if (!s) {
           free(chr);
           return NULL;
       }
       chr->opaque = s;
       chr->chr_write = win_chr_write;
       chr->chr_add_read_handler = win_chr_add_read_handler;
       chr->chr_close = win_chr_close;
       
       if (win_chr_pipe_init(s, filename) < 0) {
           free(s);
           free(chr);
           return NULL;
       }
       return chr;
   }
   
   CharDriverState *qemu_chr_open_win_file(HANDLE fd_out)
   {
       CharDriverState *chr;
       WinCharState *s;
   
       chr = qemu_mallocz(sizeof(CharDriverState));
       if (!chr)
           return NULL;
       s = qemu_mallocz(sizeof(WinCharState));
       if (!s) {
           free(chr);
           return NULL;
       }
       s->hcom = fd_out;
       chr->opaque = s;
       chr->chr_write = win_chr_write;
       chr->chr_add_read_handler = win_chr_add_read_handler;
       return chr;
   }
       
   CharDriverState *qemu_chr_open_win_file_out(const char *file_out)
   {
       HANDLE fd_out;
       
       fd_out = CreateFile(file_out, GENERIC_WRITE, FILE_SHARE_READ, NULL,
                           OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
       if (fd_out == INVALID_HANDLE_VALUE)
           return NULL;
   
       return qemu_chr_open_win_file(fd_out);
   }
   #endif
   
   /***********************************************************/
   /* UDP Net console */
   
   typedef struct {
       IOCanRWHandler *fd_can_read;
       IOReadHandler *fd_read;
       void *fd_opaque;
       int fd;
       struct sockaddr_in daddr;
       char buf[1024];
       int bufcnt;
       int bufptr;
       int max_size;
   } NetCharDriver;
   
   static int udp_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
   {
       NetCharDriver *s = chr->opaque;
   
       return sendto(s->fd, buf, len, 0,
                     (struct sockaddr *)&s->daddr, sizeof(struct sockaddr_in));
   }
   
   static int udp_chr_read_poll(void *opaque)
   {
       CharDriverState *chr = opaque;
       NetCharDriver *s = chr->opaque;
   
       s->max_size = s->fd_can_read(s->fd_opaque);
   
       /* If there were any stray characters in the queue process them
        * first
        */
       while (s->max_size > 0 && s->bufptr < s->bufcnt) {
           s->fd_read(s->fd_opaque, &s->buf[s->bufptr], 1);
           s->bufptr++;
           s->max_size = s->fd_can_read(s->fd_opaque);
       }
       return s->max_size;
   }
   
   static void udp_chr_read(void *opaque)
   {
       CharDriverState *chr = opaque;
       NetCharDriver *s = chr->opaque;
   
       if (s->max_size == 0)
           return;
       s->bufcnt = recv(s->fd, s->buf, sizeof(s->buf), 0);
       s->bufptr = s->bufcnt;
       if (s->bufcnt <= 0)
           return;
   
       s->bufptr = 0;
       while (s->max_size > 0 && s->bufptr < s->bufcnt) {
           s->fd_read(s->fd_opaque, &s->buf[s->bufptr], 1);
           s->bufptr++;
           s->max_size = s->fd_can_read(s->fd_opaque);
       }
   }
   
   static void udp_chr_add_read_handler(CharDriverState *chr,
                                       IOCanRWHandler *fd_can_read,
                                       IOReadHandler *fd_read, void *opaque)
   {
       NetCharDriver *s = chr->opaque;
   
       if (s->fd >= 0) {
           s->fd_can_read = fd_can_read;
           s->fd_read = fd_read;
           s->fd_opaque = opaque;
           qemu_set_fd_handler2(s->fd, udp_chr_read_poll,
                                udp_chr_read, NULL, chr);
       }
   }
   
   int parse_host_port(struct sockaddr_in *saddr, const char *str);
   int parse_host_src_port(struct sockaddr_in *haddr,
                           struct sockaddr_in *saddr,
                           const char *str);
   
   CharDriverState *qemu_chr_open_udp(const char *def)
   {
       CharDriverState *chr = NULL;
       NetCharDriver *s = NULL;
       int fd = -1;
       struct sockaddr_in saddr;
   
       chr = qemu_mallocz(sizeof(CharDriverState));
       if (!chr)
           goto return_err;
       s = qemu_mallocz(sizeof(NetCharDriver));
       if (!s)
           goto return_err;
   
       fd = socket(PF_INET, SOCK_DGRAM, 0);
       if (fd < 0) {
           perror("socket(PF_INET, SOCK_DGRAM)");
           goto return_err;
       }
   
       if (parse_host_src_port(&s->daddr, &saddr, def) < 0) {
           printf("Could not parse: %s\n", def);
           goto return_err;
       }
   
       if (bind(fd, (struct sockaddr *)&saddr, sizeof(saddr)) < 0)
       {
           perror("bind");
           goto return_err;
       }
   
       s->fd = fd;
       s->bufcnt = 0;
       s->bufptr = 0;
       chr->opaque = s;
       chr->chr_write = udp_chr_write;
       chr->chr_add_read_handler = udp_chr_add_read_handler;
       return chr;
   
   return_err:
       if (chr)
           free(chr);
       if (s)
           free(s);
       if (fd >= 0)
           closesocket(fd);
       return NULL;
   }
   
   /***********************************************************/
   /* TCP Net console */
   
   typedef struct {
       IOCanRWHandler *fd_can_read;
       IOReadHandler *fd_read;
       void *fd_opaque;
       int fd, listen_fd;
       int connected;
       int max_size;
       int do_telnetopt;
   } TCPCharDriver;
   
   static void tcp_chr_accept(void *opaque);
   
   static int tcp_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
   {
       TCPCharDriver *s = chr->opaque;
       if (s->connected) {
           return send_all(s->fd, buf, len);
       } else {
           /* XXX: indicate an error ? */
           return len;
       }
   }
   
   static int tcp_chr_read_poll(void *opaque)
   {
       CharDriverState *chr = opaque;
       TCPCharDriver *s = chr->opaque;
       if (!s->connected)
           return 0;
       s->max_size = s->fd_can_read(s->fd_opaque);
       return s->max_size;
   }
   
   #define IAC 255
   #define IAC_BREAK 243
   static void tcp_chr_process_IAC_bytes(CharDriverState *chr,
                                         TCPCharDriver *s,
                                         char *buf, int *size)
   {
       /* Handle any telnet client's basic IAC options to satisfy char by
        * char mode with no echo.  All IAC options will be removed from
        * the buf and the do_telnetopt variable will be used to track the
        * state of the width of the IAC information.
        *
        * IAC commands come in sets of 3 bytes with the exception of the
        * "IAC BREAK" command and the double IAC.
        */
   
       int i;
       int j = 0;
   
       for (i = 0; i < *size; i++) {
           if (s->do_telnetopt > 1) {
               if ((unsigned char)buf[i] == IAC && s->do_telnetopt == 2) {
                   /* Double IAC means send an IAC */
                   if (j != i)
                       buf[j] = buf[i];
                   j++;
                   s->do_telnetopt = 1;
               } else {
                   if ((unsigned char)buf[i] == IAC_BREAK && s->do_telnetopt == 2) {
                       /* Handle IAC break commands by sending a serial break */
                       chr->chr_event(s->fd_opaque, CHR_EVENT_BREAK);
                       s->do_telnetopt++;
                   }
                   s->do_telnetopt++;
               }
               if (s->do_telnetopt >= 4) {
                   s->do_telnetopt = 1;
               }
           } else {
               if ((unsigned char)buf[i] == IAC) {
                   s->do_telnetopt = 2;
               } else {
                   if (j != i)
                       buf[j] = buf[i];
                   j++;
               }
           }
       }
       *size = j;
   }
   
   static void tcp_chr_read(void *opaque)
   {
       CharDriverState *chr = opaque;
       TCPCharDriver *s = chr->opaque;
       uint8_t buf[1024];
       int len, size;
   
       if (!s->connected || s->max_size <= 0)
           return;
       len = sizeof(buf);
       if (len > s->max_size)
           len = s->max_size;
       size = recv(s->fd, buf, len, 0);
       if (size == 0) {
           /* connection closed */
           s->connected = 0;
           if (s->listen_fd >= 0) {
               qemu_set_fd_handler(s->listen_fd, tcp_chr_accept, NULL, chr);
           }
           qemu_set_fd_handler(s->fd, NULL, NULL, NULL);
           closesocket(s->fd);
           s->fd = -1;
       } else if (size > 0) {
           if (s->do_telnetopt)
               tcp_chr_process_IAC_bytes(chr, s, buf, &size);
           if (size > 0)
               s->fd_read(s->fd_opaque, buf, size);
       }
   }
   
   static void tcp_chr_add_read_handler(CharDriverState *chr,
                                        IOCanRWHandler *fd_can_read,
                                       IOReadHandler *fd_read, void *opaque)
   {
       TCPCharDriver *s = chr->opaque;
   
       s->fd_can_read = fd_can_read;
       s->fd_read = fd_read;
       s->fd_opaque = opaque;
   }
   
   static void tcp_chr_connect(void *opaque)
   {
       CharDriverState *chr = opaque;
       TCPCharDriver *s = chr->opaque;
   
       s->connected = 1;
       qemu_set_fd_handler2(s->fd, tcp_chr_read_poll,
                            tcp_chr_read, NULL, chr);
   }
   
   #define IACSET(x,a,b,c) x[0] = a; x[1] = b; x[2] = c;
   static void tcp_chr_telnet_init(int fd)
   {
       char buf[3];
       /* Send the telnet negotion to put telnet in binary, no echo, single char mode */
       IACSET(buf, 0xff, 0xfb, 0x01);  /* IAC WILL ECHO */
       send(fd, (char *)buf, 3, 0);
       IACSET(buf, 0xff, 0xfb, 0x03);  /* IAC WILL Suppress go ahead */
       send(fd, (char *)buf, 3, 0);
       IACSET(buf, 0xff, 0xfb, 0x00);  /* IAC WILL Binary */
       send(fd, (char *)buf, 3, 0);
       IACSET(buf, 0xff, 0xfd, 0x00);  /* IAC DO Binary */
       send(fd, (char *)buf, 3, 0);
   }
   
   static void tcp_chr_accept(void *opaque)
   {
       CharDriverState *chr = opaque;
       TCPCharDriver *s = chr->opaque;
       struct sockaddr_in saddr;
       socklen_t len;
       int fd;
   
       for(;;) {
           len = sizeof(saddr);
           fd = accept(s->listen_fd, (struct sockaddr *)&saddr, &len);
           if (fd < 0 && errno != EINTR) {
               return;
           } else if (fd >= 0) {
               if (s->do_telnetopt)
                   tcp_chr_telnet_init(fd);
               break;
           }
       }
       socket_set_nonblock(fd);
       s->fd = fd;
       qemu_set_fd_handler(s->listen_fd, NULL, NULL, NULL);
       tcp_chr_connect(chr);
   }
   
   static void tcp_chr_close(CharDriverState *chr)
   {
       TCPCharDriver *s = chr->opaque;
       if (s->fd >= 0)
           closesocket(s->fd);
       if (s->listen_fd >= 0)
           closesocket(s->listen_fd);
       qemu_free(s);
   }
   
   static CharDriverState *qemu_chr_open_tcp(const char *host_str, 
                                             int is_telnet)
   {
       CharDriverState *chr = NULL;
       TCPCharDriver *s = NULL;
       int fd = -1, ret, err, val;
       int is_listen = 0;
       int is_waitconnect = 1;
       const char *ptr;
       struct sockaddr_in saddr;
   
       if (parse_host_port(&saddr, host_str) < 0)
           goto fail;
   
       ptr = host_str;
       while((ptr = strchr(ptr,','))) {
           ptr++;
           if (!strncmp(ptr,"server",6)) {
               is_listen = 1;
           } else if (!strncmp(ptr,"nowait",6)) {
               is_waitconnect = 0;
           } else {
               printf("Unknown option: %s\n", ptr);
               goto fail;
           }
       }
       if (!is_listen)
           is_waitconnect = 0;
   
     chr = qemu_mallocz(sizeof(CharDriverState));      chr = qemu_mallocz(sizeof(CharDriverState));
     if (!chr)      if (!chr)
         return NULL;          goto fail;
     s = qemu_mallocz(sizeof(WinCharState));      s = qemu_mallocz(sizeof(TCPCharDriver));
     if (!s) {      if (!s)
         free(chr);          goto fail;
         return NULL;  
     }  
     chr->opaque = s;  
     chr->chr_write = win_chr_write;  
     chr->chr_add_read_handler = win_chr_add_read_handler;  
     chr->chr_close = win_chr_close;  
           
     if (win_chr_pipe_init(s, filename) < 0) {      fd = socket(PF_INET, SOCK_STREAM, 0);
         free(s);      if (fd < 0) 
         free(chr);          goto fail;
         return NULL;  
     }  
     return chr;  
 }  
   
 CharDriverState *qemu_chr_open_win_file(HANDLE fd_out)      if (!is_waitconnect)
 {          socket_set_nonblock(fd);
     CharDriverState *chr;  
     WinCharState *s;  
   
     chr = qemu_mallocz(sizeof(CharDriverState));      s->connected = 0;
     if (!chr)      s->fd = -1;
         return NULL;      s->listen_fd = -1;
     s = qemu_mallocz(sizeof(WinCharState));      if (is_listen) {
     if (!s) {          /* allow fast reuse */
         free(chr);          val = 1;
         return NULL;          setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (const char *)&val, sizeof(val));
           
           ret = bind(fd, (struct sockaddr *)&saddr, sizeof(saddr));
           if (ret < 0) 
               goto fail;
           ret = listen(fd, 0);
           if (ret < 0)
               goto fail;
           s->listen_fd = fd;
           qemu_set_fd_handler(s->listen_fd, tcp_chr_accept, NULL, chr);
           if (is_telnet)
               s->do_telnetopt = 1;
       } else {
           for(;;) {
               ret = connect(fd, (struct sockaddr *)&saddr, sizeof(saddr));
               if (ret < 0) {
                   err = socket_error();
                   if (err == EINTR || err == EWOULDBLOCK) {
                   } else if (err == EINPROGRESS) {
                       break;
                   } else {
                       goto fail;
                   }
               } else {
                   s->connected = 1;
                   break;
               }
           }
           s->fd = fd;
           if (s->connected)
               tcp_chr_connect(chr);
           else
               qemu_set_fd_handler(s->fd, NULL, tcp_chr_connect, chr);
     }      }
     s->hcom = fd_out;  
     chr->opaque = s;  
     chr->chr_write = win_chr_write;  
     chr->chr_add_read_handler = win_chr_add_read_handler;  
     return chr;  
 }  
       
 CharDriverState *qemu_chr_open_win_file_out(const char *file_out)  
 {  
     HANDLE fd_out;  
           
     fd_out = CreateFile(file_out, GENERIC_WRITE, FILE_SHARE_READ, NULL,      chr->opaque = s;
                         OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);      chr->chr_write = tcp_chr_write;
     if (fd_out == INVALID_HANDLE_VALUE)      chr->chr_add_read_handler = tcp_chr_add_read_handler;
         return NULL;      chr->chr_close = tcp_chr_close;
       if (is_listen && is_waitconnect) {
           printf("QEMU waiting for connection on: %s\n", host_str);
           tcp_chr_accept(chr);
           socket_set_nonblock(s->listen_fd);
       }
   
     return qemu_chr_open_win_file(fd_out);      return chr;
    fail:
       if (fd >= 0)
           closesocket(fd);
       qemu_free(s);
       qemu_free(chr);
       return NULL;
 }  }
 #endif  
   
 CharDriverState *qemu_chr_open(const char *filename)  CharDriverState *qemu_chr_open(const char *filename)
 {  {
Line 2114  CharDriverState *qemu_chr_open(const cha Line 2535  CharDriverState *qemu_chr_open(const cha
     } else if (!strcmp(filename, "null")) {      } else if (!strcmp(filename, "null")) {
         return qemu_chr_open_null();          return qemu_chr_open_null();
     } else       } else 
       if (strstart(filename, "tcp:", &p)) {
           return qemu_chr_open_tcp(p, 0);
       } else
       if (strstart(filename, "telnet:", &p)) {
           return qemu_chr_open_tcp(p, 1);
       } else
       if (strstart(filename, "udp:", &p)) {
           return qemu_chr_open_udp(p);
       } else
 #ifndef _WIN32  #ifndef _WIN32
     if (strstart(filename, "file:", &p)) {      if (strstart(filename, "file:", &p)) {
         return qemu_chr_open_file_out(p);          return qemu_chr_open_file_out(p);
Line 2221  static int get_str_sep(char *buf, int bu Line 2651  static int get_str_sep(char *buf, int bu
     return 0;      return 0;
 }  }
   
   int parse_host_src_port(struct sockaddr_in *haddr,
                           struct sockaddr_in *saddr,
                           const char *input_str)
   {
       char *str = strdup(input_str);
       char *host_str = str;
       char *src_str;
       char *ptr;
   
       /*
        * Chop off any extra arguments at the end of the string which
        * would start with a comma, then fill in the src port information
        * if it was provided else use the "any address" and "any port".
        */
       if ((ptr = strchr(str,',')))
           *ptr = '\0';
   
       if ((src_str = strchr(input_str,'@'))) {
           *src_str = '\0';
           src_str++;
       }
   
       if (parse_host_port(haddr, host_str) < 0)
           goto fail;
   
       if (!src_str || *src_str == '\0')
           src_str = ":0";
   
       if (parse_host_port(saddr, src_str) < 0)
           goto fail;
   
       free(str);
       return(0);
   
   fail:
       free(str);
       return -1;
   }
   
 int parse_host_port(struct sockaddr_in *saddr, const char *str)  int parse_host_port(struct sockaddr_in *saddr, const char *str)
 {  {
     char buf[512];      char buf[512];
Line 2819  static int net_socket_mcast_create(struc Line 3288  static int net_socket_mcast_create(struc
     socket_set_nonblock(fd);      socket_set_nonblock(fd);
     return fd;      return fd;
 fail:  fail:
     if (fd>=0) close(fd);      if (fd >= 0) 
           closesocket(fd);
     return -1;      return -1;
 }  }
   
Line 2947  static void net_socket_accept(void *opaq Line 3417  static void net_socket_accept(void *opaq
     }      }
     s1 = net_socket_fd_init(s->vlan, fd, 1);       s1 = net_socket_fd_init(s->vlan, fd, 1); 
     if (!s1) {      if (!s1) {
         close(fd);          closesocket(fd);
     } else {      } else {
         snprintf(s1->vc->info_str, sizeof(s1->vc->info_str),          snprintf(s1->vc->info_str, sizeof(s1->vc->info_str),
                  "socket: connection from %s:%d",                    "socket: connection from %s:%d", 
Line 3248  void do_info_network(void) Line 3718  void do_info_network(void)
 /***********************************************************/  /***********************************************************/
 /* USB devices */  /* USB devices */
   
   static USBPort *used_usb_ports;
   static USBPort *free_usb_ports;
   
   /* ??? Maybe change this to register a hub to keep track of the topology.  */
   void qemu_register_usb_port(USBPort *port, void *opaque, int index,
                               usb_attachfn attach)
   {
       port->opaque = opaque;
       port->index = index;
       port->attach = attach;
       port->next = free_usb_ports;
       free_usb_ports = port;
   }
   
 static int usb_device_add(const char *devname)  static int usb_device_add(const char *devname)
 {  {
     const char *p;      const char *p;
     USBDevice *dev;      USBDevice *dev;
     int i;      USBPort *port;
   
     if (!vm_usb_hub)      if (!free_usb_ports)
         return -1;  
     for(i = 0;i < MAX_VM_USB_PORTS; i++) {  
         if (!vm_usb_ports[i]->dev)  
             break;  
     }  
     if (i == MAX_VM_USB_PORTS)  
         return -1;          return -1;
   
     if (strstart(devname, "host:", &p)) {      if (strstart(devname, "host:", &p)) {
         dev = usb_host_device_open(p);          dev = usb_host_device_open(p);
         if (!dev)  
             return -1;  
     } else if (!strcmp(devname, "mouse")) {      } else if (!strcmp(devname, "mouse")) {
         dev = usb_mouse_init();          dev = usb_mouse_init();
         if (!dev)  
             return -1;  
     } else if (!strcmp(devname, "tablet")) {      } else if (!strcmp(devname, "tablet")) {
         dev = usb_tablet_init();          dev = usb_tablet_init();
         if (!dev)      } else if (strstart(devname, "disk:", &p)) {
             return -1;          dev = usb_msd_init(p);
     } else {      } else {
         return -1;          return -1;
     }      }
     usb_attach(vm_usb_ports[i], dev);      if (!dev)
           return -1;
   
       /* Find a USB port to add the device to.  */
       port = free_usb_ports;
       if (!port->next) {
           USBDevice *hub;
   
           /* Create a new hub and chain it on.  */
           free_usb_ports = NULL;
           port->next = used_usb_ports;
           used_usb_ports = port;
   
           hub = usb_hub_init(VM_USB_HUB_SIZE);
           usb_attach(port, hub);
           port = free_usb_ports;
       }
   
       free_usb_ports = port->next;
       port->next = used_usb_ports;
       used_usb_ports = port;
       usb_attach(port, dev);
     return 0;      return 0;
 }  }
   
 static int usb_device_del(const char *devname)  static int usb_device_del(const char *devname)
 {  {
       USBPort *port;
       USBPort **lastp;
     USBDevice *dev;      USBDevice *dev;
     int bus_num, addr, i;      int bus_num, addr;
     const char *p;      const char *p;
   
     if (!vm_usb_hub)      if (!used_usb_ports)
         return -1;          return -1;
   
     p = strchr(devname, '.');      p = strchr(devname, '.');
Line 3298  static int usb_device_del(const char *de Line 3795  static int usb_device_del(const char *de
     addr = strtoul(p + 1, NULL, 0);      addr = strtoul(p + 1, NULL, 0);
     if (bus_num != 0)      if (bus_num != 0)
         return -1;          return -1;
     for(i = 0;i < MAX_VM_USB_PORTS; i++) {  
         dev = vm_usb_ports[i]->dev;      lastp = &used_usb_ports;
         if (dev && dev->addr == addr)      port = used_usb_ports;
             break;      while (port && port->dev->addr != addr) {
           lastp = &port->next;
           port = port->next;
     }      }
     if (i == MAX_VM_USB_PORTS)  
       if (!port)
         return -1;          return -1;
     usb_attach(vm_usb_ports[i], NULL);  
       dev = port->dev;
       *lastp = port->next;
       usb_attach(port, NULL);
       dev->handle_destroy(dev);
       port->next = free_usb_ports;
       free_usb_ports = port;
     return 0;      return 0;
 }  }
   
Line 3328  void do_usb_del(const char *devname) Line 3834  void do_usb_del(const char *devname)
 void usb_info(void)  void usb_info(void)
 {  {
     USBDevice *dev;      USBDevice *dev;
     int i;      USBPort *port;
     const char *speed_str;      const char *speed_str;
   
     if (!vm_usb_hub) {      if (!usb_enabled) {
         term_printf("USB support not enabled\n");          term_printf("USB support not enabled\n");
         return;          return;
     }      }
   
     for(i = 0; i < MAX_VM_USB_PORTS; i++) {      for (port = used_usb_ports; port; port = port->next) {
         dev = vm_usb_ports[i]->dev;          dev = port->dev;
         if (dev) {          if (!dev)
             term_printf("Hub port %d:\n", i);              continue;
             switch(dev->speed) {          switch(dev->speed) {
             case USB_SPEED_LOW:           case USB_SPEED_LOW: 
                 speed_str = "1.5";               speed_str = "1.5"; 
                 break;              break;
             case USB_SPEED_FULL:           case USB_SPEED_FULL: 
                 speed_str = "12";               speed_str = "12"; 
                 break;              break;
             case USB_SPEED_HIGH:           case USB_SPEED_HIGH: 
                 speed_str = "480";               speed_str = "480"; 
                 break;              break;
             default:          default:
                 speed_str = "?";               speed_str = "?"; 
                 break;              break;
             }  
             term_printf("  Device %d.%d, speed %s Mb/s\n",   
                         0, dev->addr, speed_str);  
         }          }
           term_printf("  Device %d.%d, Speed %s Mb/s, Product %s\n", 
                       0, dev->addr, speed_str, dev->devname);
     }      }
 }  }
   
Line 3426  void dumb_display_init(DisplayState *ds) Line 3931  void dumb_display_init(DisplayState *ds)
     ds->dpy_refresh = dumb_refresh;      ds->dpy_refresh = dumb_refresh;
 }  }
   
 #if !defined(CONFIG_SOFTMMU)  
 /***********************************************************/  
 /* cpu signal handler */  
 static void host_segv_handler(int host_signum, siginfo_t *info,   
                               void *puc)  
 {  
     if (cpu_signal_handler(host_signum, info, puc))  
         return;  
     if (stdio_nb_clients > 0)  
         term_exit();  
     abort();  
 }  
 #endif  
   
 /***********************************************************/  /***********************************************************/
 /* I/O handling */  /* I/O handling */
   
Line 3546  void qemu_del_polling_cb(PollingFunc *fu Line 4037  void qemu_del_polling_cb(PollingFunc *fu
     }      }
 }  }
   
   #ifdef _WIN32
   /***********************************************************/
   /* Wait objects support */
   typedef struct WaitObjects {
       int num;
       HANDLE events[MAXIMUM_WAIT_OBJECTS + 1];
       WaitObjectFunc *func[MAXIMUM_WAIT_OBJECTS + 1];
       void *opaque[MAXIMUM_WAIT_OBJECTS + 1];
   } WaitObjects;
   
   static WaitObjects wait_objects = {0};
       
   int qemu_add_wait_object(HANDLE handle, WaitObjectFunc *func, void *opaque)
   {
       WaitObjects *w = &wait_objects;
   
       if (w->num >= MAXIMUM_WAIT_OBJECTS)
           return -1;
       w->events[w->num] = handle;
       w->func[w->num] = func;
       w->opaque[w->num] = opaque;
       w->num++;
       return 0;
   }
   
   void qemu_del_wait_object(HANDLE handle, WaitObjectFunc *func, void *opaque)
   {
       int i, found;
       WaitObjects *w = &wait_objects;
   
       found = 0;
       for (i = 0; i < w->num; i++) {
           if (w->events[i] == handle)
               found = 1;
           if (found) {
               w->events[i] = w->events[i + 1];
               w->func[i] = w->func[i + 1];
               w->opaque[i] = w->opaque[i + 1];
           }            
       }
       if (found)
           w->num--;
   }
   #endif
   
 /***********************************************************/  /***********************************************************/
 /* savevm/loadvm support */  /* savevm/loadvm support */
   
Line 4089  void cpu_save(QEMUFile *f, void *opaque) Line 4625  void cpu_save(QEMUFile *f, void *opaque)
     /* FPU */      /* FPU */
     for(i = 0; i < TARGET_FPREGS; i++) {      for(i = 0; i < TARGET_FPREGS; i++) {
         union {          union {
             TARGET_FPREG_T f;              float32 f;
             target_ulong i;              uint32_t i;
         } u;          } u;
         u.f = env->fpr[i];          u.f = env->fpr[i];
         qemu_put_betl(f, u.i);          qemu_put_be32(f, u.i);
     }      }
   
     qemu_put_betls(f, &env->pc);      qemu_put_betls(f, &env->pc);
Line 4125  int cpu_load(QEMUFile *f, void *opaque,  Line 4661  int cpu_load(QEMUFile *f, void *opaque, 
     /* FPU */      /* FPU */
     for(i = 0; i < TARGET_FPREGS; i++) {      for(i = 0; i < TARGET_FPREGS; i++) {
         union {          union {
             TARGET_FPREG_T f;              float32 f;
             target_ulong i;              uint32_t i;
         } u;          } u;
         u.i = qemu_get_betl(f);          u.i = qemu_get_be32(f);
         env->fpr[i] = u.f;          env->fpr[i] = u.f;
     }      }
   
Line 4422  void main_loop_wait(int timeout) Line 4958  void main_loop_wait(int timeout)
     }      }
 #ifdef _WIN32  #ifdef _WIN32
     if (ret == 0 && timeout > 0) {      if (ret == 0 && timeout > 0) {
             int err;          int err;
             HANDLE hEvents[1];          WaitObjects *w = &wait_objects;
           
             hEvents[0] = host_alarm;          ret = WaitForMultipleObjects(w->num, w->events, FALSE, timeout);
             ret = WaitForMultipleObjects(1, hEvents, FALSE, timeout);          if (WAIT_OBJECT_0 + 0 <= ret && ret <= WAIT_OBJECT_0 + w->num - 1) {
             switch(ret) {              if (w->func[ret - WAIT_OBJECT_0])
             case WAIT_OBJECT_0 + 0:                  w->func[ret - WAIT_OBJECT_0](w->opaque[ret - WAIT_OBJECT_0]);
                 break;          } else if (ret == WAIT_TIMEOUT) {
             case WAIT_TIMEOUT:          } else {
                 break;              err = GetLastError();
             default:              fprintf(stderr, "Wait error %d %d\n", ret, err);
                 err = GetLastError();          }
                 fprintf(stderr, "Wait error %d %d\n", ret, err);  
                 break;  
             }  
     }      }
 #endif  #endif
     /* poll any events */      /* poll any events */
Line 4600  void help(void) Line 5133  void help(void)
            "-cdrom file     use 'file' as IDE cdrom image (cdrom is ide1 master)\n"             "-cdrom file     use 'file' as IDE cdrom image (cdrom is ide1 master)\n"
            "-boot [a|c|d]   boot on floppy (a), hard disk (c) or CD-ROM (d)\n"             "-boot [a|c|d]   boot on floppy (a), hard disk (c) or CD-ROM (d)\n"
            "-snapshot       write to temporary files instead of disk image files\n"             "-snapshot       write to temporary files instead of disk image files\n"
   #ifdef TARGET_I386
              "-no-fd-bootchk  disable boot signature checking for floppy disks\n"
   #endif
            "-m megs         set virtual RAM size to megs MB [default=%d]\n"             "-m megs         set virtual RAM size to megs MB [default=%d]\n"
            "-smp n          set the number of CPUs to 'n' [default=1]\n"             "-smp n          set the number of CPUs to 'n' [default=1]\n"
            "-nographic      disable graphical output and redirect serial I/Os to console\n"             "-nographic      disable graphical output and redirect serial I/Os to console\n"
Line 4675  void help(void) Line 5211  void help(void)
            "                translation (t=none or lba) (usually qemu can guess them)\n"             "                translation (t=none or lba) (usually qemu can guess them)\n"
            "-L path         set the directory for the BIOS and VGA BIOS\n"             "-L path         set the directory for the BIOS and VGA BIOS\n"
 #ifdef USE_KQEMU  #ifdef USE_KQEMU
              "-kernel-kqemu   enable KQEMU full virtualization (default is user mode only)\n"
            "-no-kqemu       disable KQEMU kernel module usage\n"             "-no-kqemu       disable KQEMU kernel module usage\n"
 #endif  #endif
 #ifdef USE_CODE_COPY  #ifdef USE_CODE_COPY
Line 4683  void help(void) Line 5220  void help(void)
 #ifdef TARGET_I386  #ifdef TARGET_I386
            "-std-vga        simulate a standard VGA card with VESA Bochs Extensions\n"             "-std-vga        simulate a standard VGA card with VESA Bochs Extensions\n"
            "                (default is CL-GD5446 PCI VGA)\n"             "                (default is CL-GD5446 PCI VGA)\n"
              "-no-acpi        disable ACPI\n"
 #endif  #endif
            "-loadvm file    start right away with a saved state (loadvm in monitor)\n"             "-loadvm file    start right away with a saved state (loadvm in monitor)\n"
            "-vnc display    start a VNC server on display\n"             "-vnc display    start a VNC server on display\n"
Line 4694  void help(void) Line 5232  void help(void)
            "\n"             "\n"
            "When using -nographic, press 'ctrl-a h' to get some help.\n"             "When using -nographic, press 'ctrl-a h' to get some help.\n"
            ,             ,
 #ifdef CONFIG_SOFTMMU  
            "qemu",             "qemu",
 #else  
            "qemu-fast",  
 #endif  
            DEFAULT_RAM_SIZE,             DEFAULT_RAM_SIZE,
 #ifndef _WIN32  #ifndef _WIN32
            DEFAULT_NETWORK_SCRIPT,             DEFAULT_NETWORK_SCRIPT,
 #endif  #endif
            DEFAULT_GDBSTUB_PORT,             DEFAULT_GDBSTUB_PORT,
            "/tmp/qemu.log");             "/tmp/qemu.log");
 #ifndef CONFIG_SOFTMMU  
     printf("\n"  
            "NOTE: this version of QEMU is faster but it needs slightly patched OSes to\n"  
            "work. Please use the 'qemu' executable to have a more accurate (but slower)\n"  
            "PC emulation.\n");  
 #endif  
     exit(1);      exit(1);
 }  }
   
Line 4729  enum { Line 5257  enum {
     QEMU_OPTION_cdrom,      QEMU_OPTION_cdrom,
     QEMU_OPTION_boot,      QEMU_OPTION_boot,
     QEMU_OPTION_snapshot,      QEMU_OPTION_snapshot,
   #ifdef TARGET_I386
       QEMU_OPTION_no_fd_bootchk,
   #endif
     QEMU_OPTION_m,      QEMU_OPTION_m,
     QEMU_OPTION_nographic,      QEMU_OPTION_nographic,
 #ifdef HAS_AUDIO  #ifdef HAS_AUDIO
Line 4770  enum { Line 5301  enum {
     QEMU_OPTION_usbdevice,      QEMU_OPTION_usbdevice,
     QEMU_OPTION_smp,      QEMU_OPTION_smp,
     QEMU_OPTION_vnc,      QEMU_OPTION_vnc,
       QEMU_OPTION_no_acpi,
 };  };
   
 typedef struct QEMUOption {  typedef struct QEMUOption {
Line 4791  const QEMUOption qemu_options[] = { Line 5323  const QEMUOption qemu_options[] = {
     { "cdrom", HAS_ARG, QEMU_OPTION_cdrom },      { "cdrom", HAS_ARG, QEMU_OPTION_cdrom },
     { "boot", HAS_ARG, QEMU_OPTION_boot },      { "boot", HAS_ARG, QEMU_OPTION_boot },
     { "snapshot", 0, QEMU_OPTION_snapshot },      { "snapshot", 0, QEMU_OPTION_snapshot },
   #ifdef TARGET_I386
       { "no-fd-bootchk", 0, QEMU_OPTION_no_fd_bootchk },
   #endif
     { "m", HAS_ARG, QEMU_OPTION_m },      { "m", HAS_ARG, QEMU_OPTION_m },
     { "nographic", 0, QEMU_OPTION_nographic },      { "nographic", 0, QEMU_OPTION_nographic },
     { "k", HAS_ARG, QEMU_OPTION_k },      { "k", HAS_ARG, QEMU_OPTION_k },
Line 4842  const QEMUOption qemu_options[] = { Line 5377  const QEMUOption qemu_options[] = {
     /* temporary options */      /* temporary options */
     { "usb", 0, QEMU_OPTION_usb },      { "usb", 0, QEMU_OPTION_usb },
     { "cirrusvga", 0, QEMU_OPTION_cirrusvga },      { "cirrusvga", 0, QEMU_OPTION_cirrusvga },
       { "no-acpi", 0, QEMU_OPTION_no_acpi },
     { NULL },      { NULL },
 };  };
   
Line 5034  static void select_soundhw (const char * Line 5570  static void select_soundhw (const char *
 }  }
 #endif  #endif
   
   #ifdef _WIN32
   static BOOL WINAPI qemu_ctrl_handler(DWORD type)
   {
       exit(STATUS_CONTROL_C_EXIT);
       return TRUE;
   }
   #endif
   
 #define MAX_NET_CLIENTS 32  #define MAX_NET_CLIENTS 32
   
 int main(int argc, char **argv)  int main(int argc, char **argv)
Line 5061  int main(int argc, char **argv) Line 5605  int main(int argc, char **argv)
     int parallel_device_index;      int parallel_device_index;
     const char *loadvm = NULL;      const char *loadvm = NULL;
     QEMUMachine *machine;      QEMUMachine *machine;
     char usb_devices[MAX_VM_USB_PORTS][128];      char usb_devices[MAX_USB_CMDLINE][128];
     int usb_devices_index;      int usb_devices_index;
   
     LIST_INIT (&vm_change_state_head);      LIST_INIT (&vm_change_state_head);
 #if !defined(CONFIG_SOFTMMU)  #ifndef _WIN32
     /* we never want that malloc() uses mmap() */      {
     mallopt(M_MMAP_THRESHOLD, 4096 * 1024);          struct sigaction act;
           sigfillset(&act.sa_mask);
           act.sa_flags = 0;
           act.sa_handler = SIG_IGN;
           sigaction(SIGPIPE, &act, NULL);
       }
   #else
       SetConsoleCtrlHandler(qemu_ctrl_handler, TRUE);
       /* Note: cpu_interrupt() is currently not SMP safe, so we force
          QEMU to run on a single CPU */
       {
           HANDLE h;
           DWORD mask, smask;
           int i;
           h = GetCurrentProcess();
           if (GetProcessAffinityMask(h, &mask, &smask)) {
               for(i = 0; i < 32; i++) {
                   if (mask & (1 << i))
                       break;
               }
               if (i != 32) {
                   mask = 1 << i;
                   SetProcessAffinityMask(h, mask);
               }
           }
       }
 #endif  #endif
   
     register_machines();      register_machines();
     machine = first_machine;      machine = first_machine;
     initrd_filename = NULL;      initrd_filename = NULL;
Line 5248  int main(int argc, char **argv) Line 5818  int main(int argc, char **argv)
             case QEMU_OPTION_fdb:              case QEMU_OPTION_fdb:
                 fd_filename[1] = optarg;                  fd_filename[1] = optarg;
                 break;                  break;
   #ifdef TARGET_I386
               case QEMU_OPTION_no_fd_bootchk:
                   fd_bootchk = 0;
                   break;
   #endif
             case QEMU_OPTION_no_code_copy:              case QEMU_OPTION_no_code_copy:
                 code_copy_enabled = 0;                  code_copy_enabled = 0;
                 break;                  break;
Line 5420  int main(int argc, char **argv) Line 5995  int main(int argc, char **argv)
                 break;                  break;
             case QEMU_OPTION_usbdevice:              case QEMU_OPTION_usbdevice:
                 usb_enabled = 1;                  usb_enabled = 1;
                 if (usb_devices_index >= MAX_VM_USB_PORTS) {                  if (usb_devices_index >= MAX_USB_CMDLINE) {
                     fprintf(stderr, "Too many USB devices\n");                      fprintf(stderr, "Too many USB devices\n");
                     exit(1);                      exit(1);
                 }                  }
Line 5443  int main(int argc, char **argv) Line 6018  int main(int argc, char **argv)
                     exit(1);                      exit(1);
                 }                  }
                 break;                  break;
               case QEMU_OPTION_no_acpi:
                   acpi_enabled = 0;
                   break;
             }              }
         }          }
     }      }
Line 5467  int main(int argc, char **argv) Line 6045  int main(int argc, char **argv)
             boot_device = 'd';              boot_device = 'd';
     }      }
   
 #if !defined(CONFIG_SOFTMMU)  
     /* must avoid mmap() usage of glibc by setting a buffer "by hand" */  
     {  
         static uint8_t stdout_buf[4096];  
         setvbuf(stdout, stdout_buf, _IOLBF, sizeof(stdout_buf));  
     }  
 #else  
     setvbuf(stdout, NULL, _IOLBF, 0);      setvbuf(stdout, NULL, _IOLBF, 0);
 #endif  
           
       init_timers();
       init_timer_alarm();
   
 #ifdef _WIN32  #ifdef _WIN32
     socket_init();      socket_init();
 #endif  #endif
Line 5499  int main(int argc, char **argv) Line 6072  int main(int argc, char **argv)
     /* init the memory */      /* init the memory */
     phys_ram_size = ram_size + vga_ram_size + bios_size;      phys_ram_size = ram_size + vga_ram_size + bios_size;
   
 #ifdef CONFIG_SOFTMMU  
     phys_ram_base = qemu_vmalloc(phys_ram_size);      phys_ram_base = qemu_vmalloc(phys_ram_size);
     if (!phys_ram_base) {      if (!phys_ram_base) {
         fprintf(stderr, "Could not allocate physical memory\n");          fprintf(stderr, "Could not allocate physical memory\n");
         exit(1);          exit(1);
     }      }
 #else  
     /* as we must map the same page at several addresses, we must use  
        a fd */  
     {  
         const char *tmpdir;  
   
         tmpdir = getenv("QEMU_TMPDIR");  
         if (!tmpdir)  
             tmpdir = "/tmp";  
         snprintf(phys_ram_file, sizeof(phys_ram_file), "%s/vlXXXXXX", tmpdir);  
         if (mkstemp(phys_ram_file) < 0) {  
             fprintf(stderr, "Could not create temporary memory file '%s'\n",   
                     phys_ram_file);  
             exit(1);  
         }  
         phys_ram_fd = open(phys_ram_file, O_CREAT | O_TRUNC | O_RDWR, 0600);  
         if (phys_ram_fd < 0) {  
             fprintf(stderr, "Could not open temporary memory file '%s'\n",   
                     phys_ram_file);  
             exit(1);  
         }  
         ftruncate(phys_ram_fd, phys_ram_size);  
         unlink(phys_ram_file);  
         phys_ram_base = mmap(get_mmap_addr(phys_ram_size),   
                              phys_ram_size,   
                              PROT_WRITE | PROT_READ, MAP_SHARED | MAP_FIXED,   
                              phys_ram_fd, 0);  
         if (phys_ram_base == MAP_FAILED) {  
             fprintf(stderr, "Could not map physical memory\n");  
             exit(1);  
         }  
     }  
 #endif  
   
     /* we always create the cdrom drive, even if no disk is there */      /* we always create the cdrom drive, even if no disk is there */
     bdrv_init();      bdrv_init();
Line 5588  int main(int argc, char **argv) Line 6127  int main(int argc, char **argv)
         }          }
     }      }
   
     /* init USB devices */  
     if (usb_enabled) {  
         vm_usb_hub = usb_hub_init(vm_usb_ports, MAX_VM_USB_PORTS);  
         for(i = 0; i < usb_devices_index; i++) {  
             if (usb_device_add(usb_devices[i]) < 0) {  
                 fprintf(stderr, "Warning: could not add USB device %s\n",  
                         usb_devices[i]);  
             }  
         }  
     }  
   
     register_savevm("timer", 0, 1, timer_save, timer_load, NULL);      register_savevm("timer", 0, 1, timer_save, timer_load, NULL);
     register_savevm("ram", 0, 1, ram_save, ram_load, NULL);      register_savevm("ram", 0, 1, ram_save, ram_load, NULL);
   
     init_ioports();      init_ioports();
     cpu_calibrate_ticks();  
   
     /* terminal init */      /* terminal init */
     if (nographic) {      if (nographic) {
Line 5636  int main(int argc, char **argv) Line 6163  int main(int argc, char **argv)
                 exit(1);                  exit(1);
             }              }
             if (!strcmp(serial_devices[i], "vc"))              if (!strcmp(serial_devices[i], "vc"))
                 qemu_chr_printf(serial_hds[i], "serial%d console\n", i);                  qemu_chr_printf(serial_hds[i], "serial%d console\r\n", i);
         }          }
     }      }
   
Line 5649  int main(int argc, char **argv) Line 6176  int main(int argc, char **argv)
                 exit(1);                  exit(1);
             }              }
             if (!strcmp(parallel_devices[i], "vc"))              if (!strcmp(parallel_devices[i], "vc"))
                 qemu_chr_printf(parallel_hds[i], "parallel%d console\n", i);                  qemu_chr_printf(parallel_hds[i], "parallel%d console\r\n", i);
         }  
     }  
   
     /* setup cpu signal handlers for MMU / self modifying code handling */  
 #if !defined(CONFIG_SOFTMMU)  
       
 #if defined (TARGET_I386) && defined(USE_CODE_COPY)  
     {  
         stack_t stk;  
         signal_stack = memalign(16, SIGNAL_STACK_SIZE);  
         stk.ss_sp = signal_stack;  
         stk.ss_size = SIGNAL_STACK_SIZE;  
         stk.ss_flags = 0;  
   
         if (sigaltstack(&stk, NULL) < 0) {  
             perror("sigaltstack");  
             exit(1);  
         }          }
     }      }
 #endif  
     {  
         struct sigaction act;  
           
         sigfillset(&act.sa_mask);  
         act.sa_flags = SA_SIGINFO;  
 #if defined (TARGET_I386) && defined(USE_CODE_COPY)  
         act.sa_flags |= SA_ONSTACK;  
 #endif  
         act.sa_sigaction = host_segv_handler;  
         sigaction(SIGSEGV, &act, NULL);  
         sigaction(SIGBUS, &act, NULL);  
 #if defined (TARGET_I386) && defined(USE_CODE_COPY)  
         sigaction(SIGFPE, &act, NULL);  
 #endif  
     }  
 #endif  
   
 #ifndef _WIN32  
     {  
         struct sigaction act;  
         sigfillset(&act.sa_mask);  
         act.sa_flags = 0;  
         act.sa_handler = SIG_IGN;  
         sigaction(SIGPIPE, &act, NULL);  
     }  
 #endif  
     init_timers();  
   
     machine->init(ram_size, vga_ram_size, boot_device,      machine->init(ram_size, vga_ram_size, boot_device,
                   ds, fd_filename, snapshot,                    ds, fd_filename, snapshot,
                   kernel_filename, kernel_cmdline, initrd_filename);                    kernel_filename, kernel_cmdline, initrd_filename);
   
       /* init USB devices */
       if (usb_enabled) {
           for(i = 0; i < usb_devices_index; i++) {
               if (usb_device_add(usb_devices[i]) < 0) {
                   fprintf(stderr, "Warning: could not add USB device %s\n",
                           usb_devices[i]);
               }
           }
       }
   
     gui_timer = qemu_new_timer(rt_clock, gui_update, NULL);      gui_timer = qemu_new_timer(rt_clock, gui_update, NULL);
     qemu_mod_timer(gui_timer, qemu_get_clock(rt_clock));      qemu_mod_timer(gui_timer, qemu_get_clock(rt_clock));
   

Removed from v.1.1.1.3  
changed lines
  Added in v.1.1.1.4


unix.superglobalmegacorp.com