]> xenbits.xensource.com Git - qemu-xen-4.4-testing.git/commitdiff
Merge branch 'qemu'
authorIan Jackson <ian.jackson@eu.citrix.com>
Wed, 22 Oct 2008 16:45:28 +0000 (17:45 +0100)
committerIan Jackson <Ian.Jackson@eu.citrix.com>
Wed, 22 Oct 2008 16:45:28 +0000 (17:45 +0100)
Conflicts:

Makefile
audio/sys-queue.h
block-cow.c
block-raw-posix.c
configure
console.c
console.h
exec-all.h
hw/cirrus_vga.c
hw/ide.c
hw/ne2000.c
hw/pc.c
hw/pcnet.c
hw/rtl8139.c
hw/scsi-disk.c
hw/serial.c
hw/usb-hid.c
hw/usb-uhci.c
hw/vga.c
monitor.c
sdl.c
vl.c
vnc.c
vnc_keysym.h
vnchextile.h

53 files changed:
1  2 
.gitignore
Makefile
Makefile.target
audio/mixeng.c
block-qcow.c
block-raw-posix.c
block.c
configure
console.c
console.h
cutils.c
exec-all.h
hw/boards.h
hw/cirrus_vga.c
hw/dma.c
hw/eepro100.c
hw/ide.c
hw/iommu.c
hw/lsi53c895a.c
hw/ne2000.c
hw/pass-through.h
hw/pc.c
hw/pc.h
hw/pci.c
hw/pcnet.c
hw/rtl8139.c
hw/scsi-disk.c
hw/serial.c
hw/usb-hid.c
hw/usb-uhci.c
hw/usb.h
hw/vga.c
hw/vga_int.h
hw/vmware_vga.c
i386-dm/cpu.h
i386-dm/exec-dm.c
i386-dm/hookslib.mak
keymaps.c
monitor.c
osdep.c
qemu-char.h
qemu-common.h
qemu-lock.h
sysemu.h
tests/Makefile
vl.c
vnc.c
vnc_keysym.h
xen-config-host.h
xen-config-host.mak
xen-hooks.mak
xen-vl-extra.c
xenstore.c

diff --cc .gitignore
index 613216c063e91a6456c8a0317f3f2c22df10e263,4f27830fbc3b848991f5757744bc22aaf41acc3d..7704dfe3618a8fb1d38aa2a760aae36573bf8982
@@@ -26,13 -31,5 +31,12 @@@ qemu-nbd.po
  *.tp
  *.vr
  *.d
- *.[oa]
+ *.o
  *~
 +
 +i386-dm/Makefile
 +i386-dm/config.mak
 +i386-dm/qemu-dm
 +qemu-img-xen
 +dyngen-xen
 +dist
diff --cc Makefile
index bebd244af249e421a167f83097977f46ecc74f88,2693387248e98f8b4665c15b2688c9ad936d7ae8..e31fe822b125871cc847ef95d5aace044f807bc9
+++ b/Makefile
@@@ -24,20 -24,26 +24,33 @@@ endi
  
  LIBS+=$(AIOLIBS)
  
- all: $(TOOLS) $(DOCS) recurse-all 
+ ifdef CONFIG_SOLARIS
+ LIBS+=-lsocket -lnsl -lresolv
+ endif
+ ifdef CONFIG_WIN32
+ LIBS+=-lwinmm -lws2_32 -liphlpapi
+ endif
  
- subdir-%: libqemu_common.a
+ all: $(TOOLS) $(DOCS) recurse-all
+ SUBDIR_RULES=$(patsubst %,subdir-%, $(TARGET_DIRS))
 -subdir-%: dyngen$(EXESUF)
++subdir-%:
        $(MAKE) -C $(subst subdir-,,$@) all
  
- recurse-all: $(patsubst %,subdir-%, $(TARGET_DIRS))
+ $(filter %-softmmu,$(SUBDIR_RULES)): libqemu_common.a
+ $(filter %-user,$(SUBDIR_RULES)): libqemu_user.a
+ recurse-all: $(SUBDIR_RULES)
  
 +tapdisk-ioemu: CPPFLAGS += -I$(XEN_ROOT)/tools/libxc
 +tapdisk-ioemu: CPPFLAGS += -I$(XEN_ROOT)/tools/blktap/lib
 +tapdisk-ioemu: CPPFLAGS += -I$(XEN_ROOT)/tools/xenstore
 +tapdisk-ioemu: CPPFLAGS += -I$(XEN_ROOT)/tools/include
 +tapdisk-ioemu: tapdisk-ioemu.c cutils.c block.c block-raw.c block-cow.c block-qcow.c aes.c block-vmdk.c block-cloop.c block-dmg.c block-bochs.c block-vpc.c block-vvfat.c block-qcow2.c hw/xen_blktap.c osdep.c
 +      $(CC) -DQEMU_TOOL $(CFLAGS) $(CPPFLAGS) $(BASE_CFLAGS) $(LDFLAGS) $(BASE_LDFLAGS) -o $@ $^ -lz $(LIBS)
 +
  #######################################################################
  # BLOCK_OBJS is code used by both qemu system emulation and qemu-img
  
@@@ -165,11 -188,11 +197,11 @@@ qemu-img$(EXESUF): qemu-img.o qemu-tool
  %.o: %.c
        $(CC) $(CFLAGS) $(CPPFLAGS) -c -o $@ $<
  
+ qemu-nbd$(EXESUF):  qemu-nbd.o qemu-tool.o osdep.o $(BLOCK_OBJS)
+       $(CC) $(LDFLAGS) -o $@ $^ -lz $(LIBS)
  # dyngen host tool
 -dyngen$(EXESUF): dyngen.c osdep.o
 +dyngen$(EXESUF): dyngen.o osdep.o
        $(HOST_CC) $(CFLAGS) $(CPPFLAGS) -o $@ $^
  
  clean:
diff --cc Makefile.target
index 577703366fce404b22fe1076de83ac729683e625,f6ec8efba9953c44334173820a6433841bb4592f..f82eb78d04b32e82424bed4fd03fcdfbbaed7a36
@@@ -687,11 -669,8 +675,11 @@@ LDFLAGS+=-
  main.o: CFLAGS+=-p
  endif
  
 +-include hooks.mak
 +all: $(PROGS)
 +
  $(QEMU_PROG): $(OBJS) ../libqemu_common.a libqemu.a
-       $(CC) $(LDFLAGS) -o $@ $^ $(LIBS) $(SDL_LIBS) $(COCOA_LIBS) $(CURSES_LIBS) $(BRLAPI_LIBS)
+       $(CC) $(LDFLAGS) -o $@ $^ $(LIBS) $(SDL_LIBS) $(COCOA_LIBS) $(CURSES_LIBS) $(BRLAPI_LIBS) $(VDE_LIBS)
  
  endif # !CONFIG_USER_ONLY
  
diff --cc audio/mixeng.c
Simple merge
diff --cc block-qcow.c
Simple merge
index 23641755b1a159082b17e17b2b5ec3b65cb7636b,92b4038e72965b7eeafa17c790c785d459b3f5d7..d758743af070ab1848d4284aceed83c1f5d74330
@@@ -237,95 -442,71 +442,72 @@@ static int raw_pwrite(BlockDriverState 
  /***********************************************************/
  /* Unix AIO using POSIX AIO */
  
 +#ifndef NO_AIO
  typedef struct RawAIOCB {
      BlockDriverAIOCB common;
+     int fd;
      struct aiocb aiocb;
      struct RawAIOCB *next;
+     int ret;
  } RawAIOCB;
  
- static int aio_sig_num = SIGUSR2;
- static RawAIOCB *first_aio; /* AIO issued */
- static int aio_initialized = 0;
- static int aio_sig_pipe[2];
- static void aio_signal_handler(int signum)
+ typedef struct PosixAioState
  {
-     int e;
-     e = errno;
-     write(aio_sig_pipe[1],"",1); /* ignore errors as they should be EAGAIN */
- #ifndef QEMU_IMG
-     CPUState *env = cpu_single_env;
-     if (env) {
-         /* stop the currently executing cpu because a timer occured */
-         cpu_interrupt(env, CPU_INTERRUPT_EXIT);
- #ifdef USE_KQEMU
-         if (env->kqemu_enabled) {
-             kqemu_cpu_interrupt(env);
-         }
- #endif
-     }
- #endif
-     errno = e;
- }
- static void qemu_aio_sig_pipe_read(void *opaque_ignored) {
-     qemu_aio_poll();
- }
+     int rfd, wfd;
+     RawAIOCB *first_aio;
+ } PosixAioState;
  
void qemu_aio_init(void)
static int raw_fd_pool_get(BDRVRawState *s)
  {
-     struct sigaction act;
-     int ret;
+     int i;
  
-     ret = pipe(aio_sig_pipe);
-     if (ret) { perror("qemu_aio_init pipe failed"); exit(-1); }
-     fcntl(aio_sig_pipe[0], F_SETFL, O_NONBLOCK);
-     fcntl(aio_sig_pipe[1], F_SETFL, O_NONBLOCK);
+     for (i = 0; i < RAW_FD_POOL_SIZE; i++) {
+         /* already in use */
+         if (s->fd_pool[i] != -1)
+             continue;
  
- #ifndef QEMU_IMG
-     ret = qemu_set_fd_handler2(aio_sig_pipe[0], NULL,
-                                qemu_aio_sig_pipe_read, NULL, NULL);
-     if (ret) {
-         fputs("qemu_aio_init set_fd_handler failed\n",stderr);
-         exit(-1);
+         /* try to dup file descriptor */
+         s->fd_pool[i] = dup(s->fd);
+         if (s->fd_pool[i] != -1)
+             return s->fd_pool[i];
      }
- #endif
  
-     aio_initialized = 1;
+     /* we couldn't dup the file descriptor so just use the main one */
+     return s->fd;
+ }
  
-     sigfillset(&act.sa_mask);
-     act.sa_flags = 0; /* do not restart syscalls to interrupt select() */
-     act.sa_handler = aio_signal_handler;
-     sigaction(aio_sig_num, &act, NULL);
+ static void raw_fd_pool_put(RawAIOCB *acb)
+ {
+     BDRVRawState *s = acb->common.bs->opaque;
+     int i;
  
- #if defined(__GLIBC__) && defined(__linux__)
-     {
-         /* XXX: aio thread exit seems to hang on RedHat 9 and this init
-            seems to fix the problem. */
-         struct aioinit ai;
-         memset(&ai, 0, sizeof(ai));
-         ai.aio_threads = 1;
-         ai.aio_num = 1;
-         ai.aio_idle_time = 365 * 100000;
-         aio_init(&ai);
+     for (i = 0; i < RAW_FD_POOL_SIZE; i++) {
+         if (s->fd_pool[i] == acb->fd) {
+             close(s->fd_pool[i]);
+             s->fd_pool[i] = -1;
+         }
      }
- #endif
  }
  
void qemu_aio_poll(void)
static void posix_aio_read(void *opaque)
  {
+     PosixAioState *s = opaque;
      RawAIOCB *acb, **pacb;
      int ret;
+     ssize_t len;
  
-     /* eat any pending signal notifications */
-     {
-         char dummy_buf[16];
-         read(aio_sig_pipe[0],dummy_buf,sizeof(dummy_buf));
-     }
+     do {
+         char byte;
+         len = read(s->rfd, &byte, 1);
+         if (len == -1 && errno == EINTR)
+             continue;
+         if (len == -1 && errno == EAGAIN)
+             break;
+     } while (len == -1);
  
      for(;;) {
-         pacb = &first_aio;
+         pacb = &s->first_aio;
          for(;;) {
              acb = *pacb;
              if (!acb)
@@@ -499,8 -758,26 +759,27 @@@ static void raw_aio_cancel(BlockDriverA
          pacb = &acb->next;
      }
  }
 +#endif
  
+ #else /* CONFIG_AIO */
+ static int posix_aio_init(void)
+ {
+     return 0;
+ }
+ #endif /* CONFIG_AIO */
+ static void raw_close_fd_pool(BDRVRawState *s)
+ {
+     int i;
+     for (i = 0; i < RAW_FD_POOL_SIZE; i++) {
+         if (s->fd_pool[i] != -1) {
+             close(s->fd_pool[i]);
+             s->fd_pool[i] = -1;
+         }
+     }
+ }
  static void raw_close(BlockDriverState *bs)
  {
      BDRVRawState *s = bs->opaque;
@@@ -610,7 -913,6 +915,7 @@@ BlockDriver bdrv_raw = 
      .bdrv_aio_flush = raw_aio_flush,
      .aiocb_size = sizeof(RawAIOCB),
  #endif
-     .protocol_name = "file",
++ /* .protocol_name = "file", //  removed upstream, try removing it here -iwj */
      .bdrv_pread = raw_pread,
      .bdrv_pwrite = raw_pwrite,
      .bdrv_truncate = raw_truncate,
diff --cc block.c
Simple merge
diff --cc configure
index 994a4c83ca0671ab44006fc59a8fd3dda8bbbfb0,c15ffd181529b2025bc22726d04d7d1731036958..3981c4131b9a3991a197c48fe45c7638ac8e1e33
+++ b/configure
@@@ -262,21 -274,19 +274,21 @@@ for opt d
    ;;
    --disable-sdl) sdl="no"
    ;;
-   --enable-coreaudio) coreaudio="yes"
 +  --disable-opengl) opengl="no"
 +  ;;
+   --fmod-lib=*) fmod_lib="$optarg"
    ;;
-   --enable-alsa) alsa="yes"
+   --fmod-inc=*) fmod_inc="$optarg"
    ;;
-   --enable-esd) esd="yes"
+   --oss-lib=*) oss_lib="$optarg"
    ;;
-   --enable-dsound) dsound="yes"
+   --audio-card-list=*) audio_card_list=`echo "$optarg" | sed -e 's/,/ /g'`
    ;;
-   --enable-fmod) fmod="yes"
+   --audio-drv-list=*) audio_drv_list="$optarg"
    ;;
-   --fmod-lib=*) fmod_lib="$optarg"
+   --enable-sparse) sparse="yes"
    ;;
-   --fmod-inc=*) fmod_inc="$optarg"
+   --disable-sparse) sparse="no"
    ;;
    --disable-vnc-tls) vnc_tls="no"
    ;;
@@@ -714,43 -800,73 +802,92 @@@ EO
  fi
  
  ##########################################
- ##########################################
- # alsa sound support libraries
 +# OpenGL test
 +
 +if test -z "$opengl" && test "$sdl" = "yes"
 +then
 +cat > $TMPC << EOF
 +#include <SDL_opengl.h>
 +#ifndef GL_TEXTURE_RECTANGLE_ARB
 +#error "Opengl doesn't support GL_TEXTURE_RECTANGLE_ARB"
 +#endif
 +int main( void ) { return (int) glGetString(GL_EXTENSIONS); }
 +EOF
 +if $cc $ARCH_CFLAGS -o $TMPE `$sdl_config --cflags --libs 2> /dev/null` -I/usr/include/GL $TMPC -lXext -lGL 2> /dev/null
 +then
 +opengl="yes"
 +else
 +opengl="no"
 +fi
 +fi
 +
+ # Sound support libraries probe
  
- if test "$alsa" = "yes" ; then
-   cat > $TMPC << EOF
- #include <alsa/asoundlib.h>
- int main(void) { snd_pcm_t **handle; return snd_pcm_close(*handle); }
+ audio_drv_probe()
+ {
+     drv=$1
+     hdr=$2
+     lib=$3
+     exp=$4
+     cfl=$5
+         cat > $TMPC << EOF
+ #include <$hdr>
+ int main(void) { $exp }
  EOF
-   if $cc $ARCH_CFLAGS -o $TMPE $TMPC -lasound 2> /dev/null ; then
-     :
-   else
-     echo
-     echo "Error: Could not find alsa"
-     echo "Make sure to have the alsa libs and headers installed."
-     echo
-     exit 1
-   fi
- fi
+     if $cc $ARCH_CFLAGS $cfl -o $TMPE $TMPC $lib 2> /dev/null ; then
+         :
+     else
+         echo
+         echo "Error: $drv check failed"
+         echo "Make sure to have the $drv libs and headers installed."
+         echo
+         exit 1
+     fi
+ }
+ audio_drv_list=`echo "$audio_drv_list" | sed -e 's/,/ /g'`
+ for drv in $audio_drv_list; do
+     case $drv in
+     alsa)
+     audio_drv_probe $drv alsa/asoundlib.h -lasound \
+         "snd_pcm_t **handle; return snd_pcm_close(*handle);"
+     ;;
+     fmod)
+     if test -z $fmod_lib || test -z $fmod_inc; then
+         echo
+         echo "Error: You must specify path to FMOD library and headers"
+         echo "Example: --fmod-inc=/path/include/fmod --fmod-lib=/path/lib/libfmod-3.74.so"
+         echo
+         exit 1
+     fi
+     audio_drv_probe $drv fmod.h $fmod_lib "return FSOUND_GetVersion();" "-I $fmod_inc"
+     ;;
+     esd)
+     audio_drv_probe $drv esd.h -lesd 'return esd_play_stream(0, 0, "", 0);'
+     ;;
+     pa)
+     audio_drv_probe $drv pulse/simple.h -lpulse-simple \
+         "pa_simple *s = NULL; pa_simple_free(s); return 0;"
+     ;;
+     oss|sdl|core|wav|dsound)
+     # XXX: Probes for CoreAudio, DirectSound, SDL(?)
+     ;;
+     *)
+     echo "$audio_possible_drivers" | grep -q "\<$drv\>" || {
+         echo
+         echo "Error: Unknown driver '$drv' selected"
+         echo "Possible drivers are: $audio_possible_drivers"
+         echo
+         exit 1
+     }
+     ;;
+     esac
+ done
  
  ##########################################
  # BrlAPI probe
@@@ -831,31 -981,11 +1002,12 @@@ echo "SDL support       $sdl
  if test "$sdl" != "no" ; then
      echo "SDL static link   $sdl_static"
  fi
 +echo "OpenGL support    $opengl"
  echo "curses support    $curses"
  echo "mingw32 support   $mingw32"
- echo "Audio support     $audio"
- echo "Adlib support     $adlib"
- echo "AC97 support      $ac97"
- echo "GUS support       $gus"
- echo "CoreAudio support $coreaudio"
- echo "ALSA support      $alsa"
- echo "EsounD support    $esd"
- echo "DSound support    $dsound"
- if test "$fmod" = "yes"; then
-     if test -z $fmod_lib || test -z $fmod_inc; then
-         echo
-         echo "Error: You must specify path to FMOD library and headers"
-         echo "Example: --fmod-inc=/path/include/fmod --fmod-lib=/path/lib/libfmod-3.74.so"
-         echo
-         exit 1
-     fi
-     fmod_support=" (lib='$fmod_lib' include='$fmod_inc')"
- else
-     fmod_support=""
- fi
- echo "FMOD support      $fmod $fmod_support"
- echo "OSS support       $oss"
+ echo "Audio drivers     $audio_drv_list"
+ echo "Extra audio cards $audio_card_list"
+ echo "Mixer emulation   $mixemu"
  echo "VNC TLS support   $vnc_tls"
  if test "$vnc_tls" = "yes" ; then
      echo "    TLS CFLAGS    $vnc_tls_cflags"
diff --cc console.c
index ba5d0deb87bbb034e9a26d3d4b88e55e293c7a0c,bec9946c429f4f6f65ddf84f0c24daed97afdd41..859454916e07eac0c4588d43a120bc0d480e4091
+++ b/console.c
@@@ -159,12 -168,23 +168,17 @@@ void vga_hw_invalidate(void
  
  void vga_hw_screen_dump(const char *filename)
  {
-     /* There is currently no was of specifying which screen we want to dump,
-        so always dump the dirst one.  */
+     TextConsole *previous_active_console;
+     previous_active_console = active_console;
+     active_console = consoles[0];
+     /* There is currently no way of specifying which screen we want to dump,
+        so always dump the first one.  */
      if (consoles[0]->hw_screen_dump)
          consoles[0]->hw_screen_dump(consoles[0]->hw, filename);
+     active_console = previous_active_console;
  }
  
 -void vga_hw_text_update(console_ch_t *chardata)
 -{
 -    if (active_console && active_console->hw_text_update)
 -        active_console->hw_text_update(active_console->hw, chardata);
 -}
 -
  /* convert a RGBA color to a color index usable in graphic primitives */
  static unsigned int vga_get_color(DisplayState *ds, unsigned int rgba)
  {
@@@ -989,17 -1047,10 +1003,17 @@@ void console_select(unsigned int index
      s = consoles[index];
      if (s) {
          active_console = s;
-         if (s->text_console) {
 -        if (s->console_type != TEXT_CONSOLE && s->g_width && s->g_height
 -            && (s->g_width != s->ds->width || s->g_height != s->ds->height))
 -            dpy_resize(s->ds, s->g_width, s->g_height);
 -        vga_hw_invalidate();
++        if (s->console_type == TEXT_CONSOLE) {
 +            if (s->g_width != s->ds->width ||
 +                s->g_height != s->ds->height) {
 +                s->g_width = s->ds->width;
 +                s->g_height = s->ds->height;
 +                text_console_resize(s);
 +            }
 +            console_refresh(s);
 +        } else {
 +            vga_hw_invalidate();
 +        }
      }
  }
  
@@@ -1123,7 -1219,7 +1182,7 @@@ static TextConsole *new_console(Display
      } else {
          /* HACK: Put graphical consoles before text consoles.  */
          for (i = nb_consoles; i > 0; i--) {
-             if (!consoles[i - 1]->text_console)
 -            if (consoles[i - 1]->console_type == GRAPHIC_CONSOLE)
++            if (!consoles[i - 1]->console_type == GRAPHIC_CONSOLE)
                  break;
              consoles[i] = consoles[i - 1];
          }
@@@ -1152,17 -1249,22 +1212,22 @@@ TextConsole *graphic_console_init(Displ
  
  int is_graphic_console(void)
  {
-     return !active_console->text_console;
+     return active_console && active_console->console_type == GRAPHIC_CONSOLE;
  }
  
- void set_color_table(DisplayState *ds)
+ int is_fixedsize_console(void)
+ {
+     return active_console && active_console->console_type != TEXT_CONSOLE;
+ }
+ void console_color_init(DisplayState *ds)
  {
      int i, j;
 -    for (j = 0; j < 2; j++) {
 -        for (i = 0; i < 8; i++) {
 -            color_table[j][i] = col_expand(ds, 
 -                   vga_get_color(ds, color_table_rgb[j][i]));
 -        }
 +    for(j = 0; j < 2; j++) {
 +      for(i = 0; i < 8; i++) {
 +          color_table[j][i] =
 +              col_expand(ds, vga_get_color(ds, color_table_rgb[j][i]));
 +      }
      }
  }
  
@@@ -1191,7 -1295,7 +1256,7 @@@ CharDriverState *text_console_init(Disp
  
      if (!color_inited) {
          color_inited = 1;
-         set_color_table(ds);
 -        console_color_init(s->ds);
++        console_color_init(ds);
      }
      s->y_displayed = 0;
      s->y_base = 0;
diff --cc console.h
index c3b113042830c6fcc08b01a1e734b8e09cfa5010,fba9e299b3351f820fefda8d24ca3a451cbee11d..d0a99c60f1812898ad2b3bcff7b632da58e02a2b
+++ b/console.h
@@@ -73,12 -81,9 +76,11 @@@ struct DisplayState 
      int width;
      int height;
      void *opaque;
 +    uint32_t *palette;
      struct QEMUTimer *gui_timer;
      uint64_t gui_timer_interval;
-     int idle;
+     int idle; /* there is nothing to update (window invisible), set by vnc/sdl */
 +    int shared_buf;
  
      void (*dpy_update)(struct DisplayState *s, int x, int y, int w, int h);
      void (*dpy_resize)(struct DisplayState *s, int w, int h);
                       int dst_x, int dst_y, int w, int h);
      void (*dpy_fill)(struct DisplayState *s, int x, int y,
                       int w, int h, uint32_t c);
 -    void (*mouse_set)(int x, int y, int on);
 -    void (*cursor_define)(int width, int height, int bpp, int hot_x, int hot_y,
 -                          uint8_t *image, uint8_t *mask);
+     void (*dpy_text_cursor)(struct DisplayState *s, int x, int y);
  };
  
  static inline void dpy_update(DisplayState *s, int x, int y, int w, int h)
@@@ -100,12 -107,18 +103,21 @@@ static inline void dpy_resize(DisplaySt
  {
      s->dpy_resize(s, w, h);
  }
 -
 +static inline void dpy_resize_shared(DisplayState *s, int w, int h, int depth, int linesize, void *pixels)
 +{
 +    s->dpy_resize_shared(s, w, h, depth, linesize, pixels);
 +}
+ static inline void dpy_cursor(DisplayState *s, int x, int y)
+ {
+     if (s->dpy_text_cursor)
+         s->dpy_text_cursor(s, x, y);
+ }
  
  typedef unsigned long console_ch_t;
+ static inline void console_write_ch(console_ch_t *dest, uint32_t ch)
+ {
+     cpu_to_le32wu((uint32_t *) dest, ch);
+ }
  
  typedef void (*vga_hw_update_ptr)(void *);
  typedef void (*vga_hw_invalidate_ptr)(void *);
@@@ -120,14 -133,19 +132,18 @@@ TextConsole *graphic_console_init(Displ
  void vga_hw_update(void);
  void vga_hw_invalidate(void);
  void vga_hw_screen_dump(const char *filename);
 -void vga_hw_text_update(console_ch_t *chardata);
  
  int is_graphic_console(void);
+ int is_fixedsize_console(void);
  CharDriverState *text_console_init(DisplayState *ds, const char *p);
  void console_select(unsigned int index);
- void set_color_table(DisplayState *ds);
+ void console_color_init(DisplayState *ds);
+ void qemu_console_resize(QEMUConsole *console, int width, int height);
+ void qemu_console_copy(QEMUConsole *console, int src_x, int src_y,
+                 int dst_x, int dst_y, int w, int h);
  
  /* sdl.c */
 -void sdl_display_init(DisplayState *ds, int full_screen, int no_frame);
 +void sdl_display_init(DisplayState *ds, int full_screen, int no_frame, int opengl_enabled);
  
  /* cocoa.m */
  void cocoa_display_init(DisplayState *ds, int full_screen);
diff --cc cutils.c
Simple merge
diff --cc exec-all.h
index f9475df95a5df24a564dbd1024480117d95b865b,6609c9a257df9854652e6855e5d7532b1a280270..cfd1b98b6387ca59ace0df1bfc7d0d2b98d9bc76
@@@ -554,7 -309,7 +309,11 @@@ void tlb_fill(target_ulong addr, int is
  
  #endif
  
 -#if defined(CONFIG_USER_ONLY)
++#if defined(CONFIG_DM)
++static inline int can_do_io(CPUState *env) { return 1; }
++#endif
++
 +#if defined(CONFIG_USER_ONLY) || defined(CONFIG_DM)
  static inline target_ulong get_phys_addr_code(CPUState *env1, target_ulong addr)
  {
      return addr;
diff --cc hw/boards.h
Simple merge
diff --cc hw/cirrus_vga.c
Simple merge
diff --cc hw/dma.c
Simple merge
diff --cc hw/eepro100.c
index 84d1e52aca267655ebd29b4b5e38b7671c7eb5c8,8db2098290a59e3d601f516c7f98d8f42422cc03..b021bef4d6bdb79924e505ea4eb296c48654d943
@@@ -40,6 -40,6 +40,7 @@@
  
  #include <assert.h>
  #include <stddef.h>             /* offsetof */
++#include <stdbool.h>
  #include "hw.h"
  #include "pci.h"
  #include "net.h"
  #define INT_MASK        0x0100
  #define DRVR_INT        0x0200  /* Driver generated interrupt. */
  
--typedef unsigned char bool;
--
  /* Offsets to the various registers.
     All accesses need not be longword aligned. */
  enum speedo_offsets {
diff --cc hw/ide.c
index dae6e7f0d3251740387a2091625a1a91ebd01203,8cf4fdc922e06475f3dafe28a923c3e10ecdc7f6..494c7ae6e4a0cceaa0df74579ff3511096e9c0ea
+++ b/hw/ide.c
@@@ -1099,10 -940,8 +1117,10 @@@ static void ide_read_dma_cb(void *opaqu
        return;
      }
  
-     if (!s->bs) return; /* yikes */
+     if (!s->bs) return; /* ouch! (see ide_flush_cb) */
  
 +    if (!s->bs) return; /* yikes */
 +
      n = s->io_buffer_size >> 9;
      sector_num = ide_get_sector(s);
      if (n > 0) {
@@@ -1227,10 -1066,8 +1245,10 @@@ static void ide_write_dma_cb(void *opaq
        return;
      }
  
-     if (!s->bs) return; /* yikes */
+     if (!s->bs) return; /* ouch! (see ide_flush_cb) */
  
 +    if (!s->bs) return; /* yikes */
 +
      n = s->io_buffer_size >> 9;
      sector_num = ide_get_sector(s);
      if (n > 0) {
@@@ -1536,10 -1373,8 +1554,10 @@@ static void ide_atapi_cmd_read_dma_cb(v
      IDEState *s = bm->ide_if;
      int data_offset, n;
  
-     if (!s->bs) return; /* yikes */
+     if (!s->bs) return; /* ouch! (see ide_flush_cb) */
  
 +    if (!s->bs) return; /* yikes */
 +
      if (ret < 0) {
          ide_atapi_io_error(s, ret);
          goto eot;
@@@ -2119,10 -2039,8 +2222,10 @@@ static void cdrom_change_cb(void *opaqu
      IDEState *s = opaque;
      uint64_t nb_sectors;
  
-     if (!s->bs) return; /* yikes */
+     if (!s->bs) return; /* ouch! (see ide_flush_cb) */
  
 +    if (!s->bs) return; /* yikes */
 +
      /* XXX: send interrupt too */
      bdrv_get_geometry(s->bs, &nb_sectors);
      s->nb_sectors = nb_sectors;
@@@ -2697,7 -2630,10 +2816,11 @@@ static void ide_data_writew(void *opaqu
      IDEState *s = ((IDEState *)opaque)->cur_drive;
      uint8_t *p;
  
+     /* PIO data access allowed only when DRQ bit is set */
+     if (!(s->status & DRQ_STAT))
+         return;
 +    buffered_pio_write(s, addr, 2);
      p = s->data_ptr;
      *(uint16_t *)p = le16_to_cpu(val);
      p += 2;
@@@ -2711,7 -2647,11 +2834,12 @@@ static uint32_t ide_data_readw(void *op
      IDEState *s = ((IDEState *)opaque)->cur_drive;
      uint8_t *p;
      int ret;
+     /* PIO data access allowed only when DRQ bit is set */
+     if (!(s->status & DRQ_STAT))
+         return 0;
 +    buffered_pio_read(s, addr, 2);
      p = s->data_ptr;
      ret = cpu_to_le16(*(uint16_t *)p);
      p += 2;
@@@ -2726,7 -2666,10 +2854,11 @@@ static void ide_data_writel(void *opaqu
      IDEState *s = ((IDEState *)opaque)->cur_drive;
      uint8_t *p;
  
+     /* PIO data access allowed only when DRQ bit is set */
+     if (!(s->status & DRQ_STAT))
+         return;
 +    buffered_pio_write(s, addr, 4);
      p = s->data_ptr;
      *(uint32_t *)p = le32_to_cpu(val);
      p += 4;
@@@ -2741,7 -2684,10 +2873,11 @@@ static uint32_t ide_data_readl(void *op
      uint8_t *p;
      int ret;
  
+     /* PIO data access allowed only when DRQ bit is set */
+     if (!(s->status & DRQ_STAT))
+         return 0;
 +    buffered_pio_read(s, addr, 4);
      p = s->data_ptr;
      ret = cpu_to_le32(*(uint32_t *)p);
      p += 4;
@@@ -3430,11 -3386,8 +3576,12 @@@ void pci_piix3_ide_init(PCIBus *bus, Bl
      pci_conf[0x0a] = 0x01; // class_sub = PCI_IDE
      pci_conf[0x0b] = 0x01; // class_base = PCI_mass_storage
      pci_conf[0x0e] = 0x00; // header_type
 +    pci_conf[0x2c] = 0x53; /* subsystem vendor: XenSource */
 +    pci_conf[0x2d] = 0x58;
 +    pci_conf[0x2e] = 0x01; /* subsystem device */
 +    pci_conf[0x2f] = 0x00;
  
+     qemu_register_reset(piix3_reset, d);
      piix3_reset(d);
  
      pci_register_io_region((PCIDevice *)d, 4, 0x10,
@@@ -3474,11 -3425,8 +3621,12 @@@ void pci_piix4_ide_init(PCIBus *bus, Bl
      pci_conf[0x0a] = 0x01; // class_sub = PCI_IDE
      pci_conf[0x0b] = 0x01; // class_base = PCI_mass_storage
      pci_conf[0x0e] = 0x00; // header_type
 +    pci_conf[0x2c] = 0x53; /* subsystem vendor: XenSource */
 +    pci_conf[0x2d] = 0x58;
 +    pci_conf[0x2e] = 0x01; /* subsystem device */
 +    pci_conf[0x2f] = 0x00;
  
+     qemu_register_reset(piix3_reset, d);
      piix3_reset(d);
  
      pci_register_io_region((PCIDevice *)d, 4, 0x10,
diff --cc hw/iommu.c
Simple merge
diff --cc hw/lsi53c895a.c
Simple merge
diff --cc hw/ne2000.c
Simple merge
index bc3ef8cbbc2e7d0b18a52962e941ac648323ae5e,0000000000000000000000000000000000000000..8aa664b9201640c46e494d7ad10d890894551d81
mode 100644,000000..100644
--- /dev/null
@@@ -1,296 -1,0 +1,296 @@@
- #include "audio/sys-queue.h"
 +/*
 + * Copyright (c) 2007, Neocleus Corporation.
 + * Copyright (c) 2007, Intel Corporation.
 + *
 + * This program is free software; you can redistribute it and/or modify it
 + * under the terms and conditions of the GNU General Public License,
 + * version 2, as published by the Free Software Foundation.
 + *
 + * This program is distributed in the hope it will be useful, but WITHOUT
 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 + * more details.
 + *
 + * You should have received a copy of the GNU General Public License along with
 + * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
 + * Place - Suite 330, Boston, MA 02111-1307 USA.
 + */
 +#ifndef __PASSTHROUGH_H__
 +#define __PASSTHROUGH_H__
 +
 +#include "hw.h"
 +#include "pci.h"
 +#include "pci/header.h"
 +#include "pci/pci.h"
 +#include "exec-all.h"
++#include "sys-queue.h"
 +
 +/* Log acesss */
 +#define PT_LOGGING_ENABLED
 +
 +#ifdef PT_LOGGING_ENABLED
 +#define PT_LOG(_f, _a...)   fprintf(logfile, "%s: " _f, __func__, ##_a)
 +#else
 +#define PT_LOG(_f, _a...)
 +#endif
 +
 +/* Some compilation flags */
 +// #define PT_DEBUG_PCI_CONFIG_ACCESS
 +
 +#define PT_MACHINE_IRQ_AUTO (0xFFFFFFFF)
 +#define PT_VIRT_DEVFN_AUTO  (-1)
 +
 +/* Misc PCI constants that should be moved to a separate library :) */
 +#define PCI_CONFIG_SIZE         (256)
 +#define PCI_EXP_DEVCAP_FLR      (1 << 28)
 +#define PCI_EXP_DEVCTL_FLR      (1 << 15)
 +#define PCI_BAR_ENTRIES         (6)
 +
 +/* because the current version of libpci (2.2.0) doesn't define these ID,
 + * so we define Capability ID here.
 + */
 +#ifndef PCI_CAP_ID_HOTPLUG
 +/* SHPC Capability List Item reg group */
 +#define PCI_CAP_ID_HOTPLUG      0x0C
 +#endif
 +
 +#ifndef PCI_CAP_ID_SSVID
 +/* Subsystem ID and Subsystem Vendor ID Capability List Item reg group */
 +#define PCI_CAP_ID_SSVID        0x0D
 +#endif
 +
 +#ifndef PCI_MSI_FLAGS_MASK_BIT
 +/* interrupt masking & reporting supported */
 +#define PCI_MSI_FLAGS_MASK_BIT  0x0100
 +#endif
 +
 +#ifndef PCI_EXP_TYPE_PCIE_BRIDGE
 +/* PCI/PCI-X to PCIE Bridge */
 +#define PCI_EXP_TYPE_PCIE_BRIDGE 0x8
 +#endif
 +
 +#ifndef PCI_EXP_TYPE_ROOT_INT_EP
 +/* Root Complex Integrated Endpoint */
 +#define PCI_EXP_TYPE_ROOT_INT_EP 0x9
 +#endif
 +
 +#ifndef PCI_EXP_TYPE_ROOT_EC
 +/* Root Complex Event Collector */
 +#define PCI_EXP_TYPE_ROOT_EC     0xa
 +#endif
 +
 +#define PT_INVALID_REG          0xFFFFFFFF      /* invalid register value */
 +#define PT_BAR_ALLF             0xFFFFFFFF      /* BAR ALLF value */
 +#define PT_BAR_MEM_RO_MASK      0x0000000F      /* BAR ReadOnly mask(Memory) */
 +#define PT_BAR_MEM_EMU_MASK     0xFFFFFFF0      /* BAR emul mask(Memory) */
 +#define PT_BAR_IO_RO_MASK       0x00000003      /* BAR ReadOnly mask(I/O) */
 +#define PT_BAR_IO_EMU_MASK      0xFFFFFFFC      /* BAR emul mask(I/O) */
 +enum {
 +    PT_BAR_FLAG_MEM = 0,                        /* Memory type BAR */
 +    PT_BAR_FLAG_IO,                             /* I/O type BAR */
 +    PT_BAR_FLAG_UPPER,                          /* upper 64bit BAR */
 +    PT_BAR_FLAG_UNUSED,                         /* unused BAR */
 +};
 +enum {
 +    GRP_TYPE_HARDWIRED = 0,                     /* 0 Hardwired reg group */
 +    GRP_TYPE_EMU,                               /* emul reg group */
 +};
 +
 +#define PT_GET_EMUL_SIZE(flag, r_size) do { \
 +    if (flag == PT_BAR_FLAG_MEM) {\
 +        r_size = (((r_size) + XC_PAGE_SIZE - 1) & ~(XC_PAGE_SIZE - 1)); \
 +    }\
 +} while(0)
 +
 +
 +struct pt_region {
 +    /* Virtual phys base & size */
 +    uint32_t e_physbase;
 +    uint32_t e_size;
 +    /* Index of region in qemu */
 +    uint32_t memory_index;
 +    /* BAR flag */
 +    uint32_t bar_flag;
 +    /* Translation of the emulated address */
 +    union {
 +        uint64_t maddr;
 +        uint64_t pio_base;
 +        uint64_t u;
 +    } access;
 +};
 +
 +struct pt_msi_info {
 +    uint32_t flags;
 +    int pirq;          /* guest pirq corresponding */
 +    uint32_t addr_lo;  /* guest message address */
 +    uint32_t addr_hi;  /* guest message upper address */
 +    uint16_t data;     /* guest message data */
 +};
 +
 +struct msix_entry_info {
 +    int pirq;          /* -1 means unmapped */
 +    int flags;         /* flags indicting whether MSI ADDR or DATA is updated */
 +    uint32_t io_mem[4];
 +};
 +
 +struct pt_msix_info {
 +    int enabled;
 +    int total_entries;
 +    int bar_index;
 +    uint64_t table_base;
 +    uint32_t table_off;
 +    uint64_t mmio_base_addr;
 +    int mmio_index;
 +    int fd;
 +    void *phys_iomem_base;
 +    struct msix_entry_info msix_entry[0];
 +};
 +
 +/*
 +    This structure holds the context of the mapping functions
 +    and data that is relevant for qemu device management.
 +*/
 +struct pt_dev {
 +    PCIDevice dev;
 +    struct pci_dev *pci_dev;                    /* libpci struct */
 +    struct pt_region bases[PCI_NUM_REGIONS];    /* Access regions */
 +    LIST_HEAD (reg_grp_tbl_listhead, pt_reg_grp_tbl) reg_grp_tbl_head;
 +                                                /* emul reg group list */
 +    struct pt_msi_info *msi;                    /* MSI virtualization */
 +    struct pt_msix_info *msix;                  /* MSI-X virtualization */
 +};
 +
 +/* Used for formatting PCI BDF into cf8 format */
 +struct pci_config_cf8 {
 +    union {
 +        unsigned int value;
 +        struct {
 +            unsigned int reserved1:2;
 +            unsigned int reg:6;
 +            unsigned int func:3;
 +            unsigned int dev:5;
 +            unsigned int bus:8;
 +            unsigned int reserved2:7;
 +            unsigned int enable:1;
 +        };
 +    };
 +};
 +
 +/* emul reg group management table */
 +struct pt_reg_grp_tbl {
 +    /* emul reg group list */
 +    LIST_ENTRY (pt_reg_grp_tbl) entries;
 +    /* emul reg group info table */
 +    struct pt_reg_grp_info_tbl *reg_grp;
 +    /* emul reg group base offset */
 +    uint32_t base_offset;
 +    /* emul reg group size */
 +    uint8_t size;
 +    /* emul reg management table list */
 +    LIST_HEAD (reg_tbl_listhead, pt_reg_tbl) reg_tbl_head;
 +};
 +
 +/* emul reg group size initialize method */
 +typedef uint8_t (*pt_reg_size_init) (struct pt_dev *ptdev, 
 +                                     struct pt_reg_grp_info_tbl *grp_reg, 
 +                                     uint32_t base_offset);
 +/* emul reg group infomation table */
 +struct pt_reg_grp_info_tbl {
 +    /* emul reg group ID */
 +    uint8_t grp_id;
 +    /* emul reg group type */
 +    uint8_t grp_type;
 +    /* emul reg group size */
 +    uint8_t grp_size;
 +    /* emul reg get size method */
 +    pt_reg_size_init size_init;
 +    /* emul reg info table */
 +    struct pt_reg_info_tbl *emu_reg_tbl;
 +};
 +
 +/* emul reg management table */
 +struct pt_reg_tbl {
 +    /* emul reg table list */
 +    LIST_ENTRY (pt_reg_tbl) entries;
 +    /* emul reg info table */
 +    struct pt_reg_info_tbl *reg;
 +    /* emul reg value */
 +    uint32_t data;
 +};
 +
 +/* emul reg initialize method */
 +typedef uint32_t (*conf_reg_init) (struct pt_dev *ptdev, 
 +                                   struct pt_reg_info_tbl *reg, 
 +                                   uint32_t real_offset);
 +/* emul reg long write method */
 +typedef int (*conf_dword_write) (struct pt_dev *ptdev,
 +                                 struct pt_reg_tbl *cfg_entry, 
 +                                 uint32_t *value, 
 +                                 uint32_t dev_value,
 +                                 uint32_t valid_mask);
 +/* emul reg word write method */
 +typedef int (*conf_word_write) (struct pt_dev *ptdev,
 +                                struct pt_reg_tbl *cfg_entry, 
 +                                uint16_t *value, 
 +                                uint16_t dev_value,
 +                                uint16_t valid_mask);
 +/* emul reg byte write method */
 +typedef int (*conf_byte_write) (struct pt_dev *ptdev,
 +                                struct pt_reg_tbl *cfg_entry, 
 +                                uint8_t *value, 
 +                                uint8_t dev_value,
 +                                uint8_t valid_mask);
 +/* emul reg long read methods */
 +typedef int (*conf_dword_read) (struct pt_dev *ptdev,
 +                                struct pt_reg_tbl *cfg_entry, 
 +                                uint32_t *value,
 +                                uint32_t valid_mask);
 +/* emul reg word read method */
 +typedef int (*conf_word_read) (struct pt_dev *ptdev,
 +                               struct pt_reg_tbl *cfg_entry, 
 +                               uint16_t *value,
 +                               uint16_t valid_mask);
 +/* emul reg byte read method */
 +typedef int (*conf_byte_read) (struct pt_dev *ptdev,
 +                               struct pt_reg_tbl *cfg_entry, 
 +                               uint8_t *value,
 +                               uint8_t valid_mask);
 +
 +/* emul reg infomation table */
 +struct pt_reg_info_tbl {
 +    /* reg relative offset */
 +    uint32_t offset;
 +    /* reg size */
 +    uint32_t size;
 +    /* reg initial value */
 +    uint32_t init_val;
 +    /* reg read only field mask (ON:RO/ROS, OFF:other) */
 +    uint32_t ro_mask;
 +    /* reg emulate field mask (ON:emu, OFF:passthrough) */
 +    uint32_t emu_mask;
 +    /* emul reg initialize method */
 +    conf_reg_init init;
 +    union {
 +        struct {
 +            /* emul reg long write method */
 +            conf_dword_write write;
 +            /* emul reg long read method */
 +            conf_dword_read read;
 +        } dw;
 +        struct {
 +            /* emul reg word write method */
 +            conf_word_write write;
 +            /* emul reg word read method */
 +            conf_word_read read;
 +        } w;
 +        struct {
 +            /* emul reg byte write method */
 +            conf_byte_write write;
 +            /* emul reg byte read method */
 +            conf_byte_read read;
 +        } b;
 +    } u;
 +};
 +
 +#endif /* __PASSTHROUGH_H__ */
 +
diff --cc hw/pc.c
index 656f755b1f7bcef772c7d6bf32e191b78ce6a855,34683e7920194fffea41136452c167d4efebd1e7..a31e4bae15cc0ed58309bac2c3a4aa871c2f5911
+++ b/hw/pc.c
  #include "smbus.h"
  #include "boards.h"
  #include "console.h"
 +#include "exec-all.h"
 +
 +#include "xen_platform.h"
+ #include "fw_cfg.h"
  
  /* output Bochs bios info messages */
  //#define DEBUG_BIOS
@@@ -126,18 -120,19 +131,22 @@@ static void pic_irq_request(void *opaqu
  {
      CPUState *env = first_cpu;
  
-     if (!level)
-         return;
-     while (env) {
-         if (apic_accept_pic_intr(env))
-             apic_local_deliver(env, APIC_LINT0);
-         env = env->next_cpu;
+     if (env->apic_state) {
+         while (env) {
+             if (apic_accept_pic_intr(env))
+                 apic_deliver_pic_intr(env, level);
+             env = env->next_cpu;
+         }
+     } else {
+         if (level)
+             cpu_interrupt(env, CPU_INTERRUPT_HARD);
+         else
+             cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
      }
  }
 +#else
 +#define pic_irq_request 0  /* see i386-dm/i8259.c:i8259_init */
 +#endif /* !CONFIG_DM */
  
  /* PC cmos mappings */
  
@@@ -577,24 -560,24 +592,24 @@@ static void load_linux(const char *kern
        prot_addr    = 0x100000;
      }
  
 -#if 0
 +#if 1
      fprintf(stderr,
-           "qemu: real_addr     = %#zx\n"
-           "qemu: cmdline_addr  = %#zx\n"
-           "qemu: prot_addr     = %#zx\n",
-           (size_t)real_addr,
-           (size_t)cmdline_addr,
-           (size_t)prot_addr);
+           "qemu: real_addr     = 0x" TARGET_FMT_plx "\n"
+           "qemu: cmdline_addr  = 0x" TARGET_FMT_plx "\n"
+           "qemu: prot_addr     = 0x" TARGET_FMT_plx "\n",
+           real_addr,
+           cmdline_addr,
+           prot_addr);
  #endif
  
 -    /* highest address for loading the initrd */
 -    if (protocol >= 0x203)
 -      initrd_max = ldl_p(header+0x22c);
 -    else
 -      initrd_max = 0x37ffffff;
 +    /* Special pages are placed at end of low RAM: pick an arbitrary one and
 +     * subtract a suitably large amount of padding (64kB) to skip BIOS data. */
 +    xc_get_hvm_param(xc_handle, domid, HVM_PARAM_BUFIOREQ_PFN, &end_low_ram);
 +    end_low_ram = (end_low_ram << 12) - (64*1024);
  
 -    if (initrd_max >= ram_size-ACPI_DATA_SIZE)
 -      initrd_max = ram_size-ACPI_DATA_SIZE-1;
 +    /* highest address for loading the initrd */
 +    initrd_max = (protocol >= 0x203) ? ldl_p(header+0x22c) : 0x37ffffff;
 +    initrd_max = MIN(initrd_max, (uint32_t)end_low_ram);
  
      /* kernel command line */
      pstrcpy_targphys(cmdline_addr, 4096, kernel_cmdline);
@@@ -795,15 -770,12 +808,14 @@@ static void pc_init1(ram_addr_t ram_siz
              fprintf(stderr, "Unable to find x86 CPU definition\n");
              exit(1);
          }
 +#ifndef CONFIG_DM
          if (i != 0)
-             env->hflags |= HF_HALTED_MASK;
+             env->halted = 1;
          if (smp_cpus > 1) {
              /* XXX: enable it in all cases */
              env->cpuid_features |= CPUID_APIC;
          }
-         register_savevm("cpu", i, 4, cpu_save, cpu_load, env);
 +#endif /* !CONFIG_DM */
          qemu_register_reset(main_cpu_reset, env);
          if (pci_enabled) {
              apic_init(env);
  
      vmport_init();
  
 +#ifndef CONFIG_DM
      /* allocate RAM */
-     ram_addr = qemu_ram_alloc(ram_size);
-     cpu_register_physical_memory(0, below_4g_mem_size, ram_addr);
+     ram_addr = qemu_ram_alloc(0xa0000);
+     cpu_register_physical_memory(0, 0xa0000, ram_addr);
+     /* Allocate, even though we won't register, so we don't break the
+      * phys_ram_base + PA assumption. This range includes vga (0xa0000 - 0xc0000),
+      * and some bios areas, which will be registered later
+      */
+     ram_addr = qemu_ram_alloc(0x100000 - 0xa0000);
+     ram_addr = qemu_ram_alloc(below_4g_mem_size - 0x100000);
+     cpu_register_physical_memory(0x100000,
+                  below_4g_mem_size - 0x100000,
+                  ram_addr);
  
      /* above 4giga memory allocation */
      if (above_4g_mem_size > 0) {
          }
      }
  
 +#ifdef CONFIG_PASSTHROUGH
 +    /* Pass-through Initialization
 +     * init libpci even direct_pci is null, as can hotplug a dev runtime
 +     */
 +    if ( pci_enabled )
 +    {
 +        rc = pt_init(pci_bus, direct_pci); 
 +        if ( rc < 0 )
 +        {
 +            fprintf(logfile, "Error: Initialization failed for pass-through devices\n");
 +            exit(1);
 +        }
 +    }
 +#endif
 +
      rtc_state = rtc_init(0x70, i8259[8]);
  
+     qemu_register_boot_set(pc_boot_set, rtc_state);
      register_ioport_read(0x92, 1, 1, ioport92_read, NULL);
      register_ioport_write(0x92, 1, 1, ioport92_write, NULL);
  
@@@ -1163,142 -1101,9 +1191,143 @@@ QEMUMachine pc_machine = 
  };
  
  QEMUMachine isapc_machine = {
-     "isapc",
-     "ISA-only PC",
-     pc_init_isa,
-     VGA_RAM_SIZE + PC_MAX_BIOS_SIZE,
+     .name = "isapc",
+     .desc = "ISA-only PC",
+     .init = pc_init_isa,
+     .ram_require = VGA_RAM_SIZE + PC_MAX_BIOS_SIZE,
+     .max_cpus = 1,
  };
 +
 +
 +
 +
 +/*
 + * Evil helper for non-relocatable kernels
 + *
 + * So it works out like this:
 + *
 + *  0x100000  - Xen HVM firmware lives here. Kernel wants to boot here
 + *
 + * You can't both live there and HVM firmware is needed first, thus
 + * our plan is
 + *
 + *  0x200000              - kernel is loaded here by QEMU
 + *  0x200000+kernel_size  - helper code is put here by QEMU
 + *
 + * code32_switch in kernel header is set to point at out helper
 + * code at 0x200000+kernel_size
 + *
 + * Our helper basically does memmove(0x100000,0x200000,kernel_size)
 + * and then jmps to  0x1000000.
 + *
 + * So we've overwritten the HVM firmware (which was no longer
 + * needed) and the non-relocatable kernel can happily boot
 + * at its usual address.
 + *
 + * Simple, eh ?
 + *
 + * Well the assembler needed to do this is fairly short:
 + *
 + *  # Load segments
 + *    cld                         
 + *    cli                         
 + *    movl $0x18,%eax
 + *    mov %ax,%ds                 
 + *    mov %ax,%es                 
 + *    mov %ax,%fs                 
 + *    mov %ax,%gs                 
 + *    mov %ax,%ss                 
 + *
 + *  # Move the kernel into position
 + *    xor    %edx,%edx            
 + *_doloop:                        
 + *    movzbl 0x600000(%edx),%eax  
 + *    mov    %al,0x100000(%edx)   
 + *    add    $0x1,%edx            
 + *    cmp    $0x500000,%edx       
 + *    jne    _doloop              
 + *
 + *  # start kernel
 + *    xorl %ebx,%ebx              
 + *    mov    $0x100000,%ecx       
 + *    jmp    *%ecx                
 + *
 + */
 +static void setup_relocator(target_phys_addr_t addr, target_phys_addr_t src, target_phys_addr_t dst, size_t len)
 +{
 +  /* Now this assembler corresponds to follow machine code, with our args from QEMU spliced in :-) */
 +  unsigned char buf[] = {
 +    /* Load segments */
 +    0xfc,                         /* cld               */
 +    0xfa,                         /* cli               */ 
 +    0xb8, 0x18, 0x00, 0x00, 0x00, /* mov    $0x18,%eax */
 +    0x8e, 0xd8,                   /* mov    %eax,%ds   */
 +    0x8e, 0xc0,                   /* mov    %eax,%es   */
 +    0x8e, 0xe0,                   /* mov    %eax,%fs   */
 +    0x8e, 0xe8,                   /* mov    %eax,%gs   */
 +    0x8e, 0xd0,                   /* mov    %eax,%ss   */
 +    0x31, 0xd2,                   /* xor    %edx,%edx  */
 +  
 +    /* Move the kernel into position */
 +    0x0f, 0xb6, 0x82, (src&0xff), ((src>>8)&0xff), ((src>>16)&0xff), ((src>>24)&0xff), /*   movzbl $src(%edx),%eax */
 +    0x88, 0x82, (dst&0xff), ((dst>>8)&0xff), ((dst>>16)&0xff), ((dst>>24)&0xff),       /*   mov    %al,$dst(%edx)  */
 +    0x83, 0xc2, 0x01,                                                                  /*   add    $0x1,%edx       */
 +    0x81, 0xfa, (len&0xff), ((len>>8)&0xff), ((len>>16)&0xff), ((len>>24)&0xff),       /*   cmp    $len,%edx       */
 +    0x75, 0xe8,                                                                        /*   jne    13 <_doloop>    */
 +
 +    /* Start kernel */
 +    0x31, 0xdb,                                                                        /*   xor    %ebx,%ebx       */
 +    0xb9, (dst&0xff), ((dst>>8)&0xff), ((dst>>16)&0xff), ((dst>>24)&0xff),             /*   mov    $dst,%ecx  */
 +    0xff, 0xe1,                                                                        /*   jmp    *%ecx           */
 +  };
 +  cpu_physical_memory_rw(addr, buf, sizeof(buf), 1);
 +  fprintf(stderr, "qemu: helper at 0x%x of size %d bytes, to move kernel of %d bytes from 0x%x to 0x%x\n",
 +        (int)addr, (int)sizeof(buf), (int)len, (int)src, (int)dst);
 +}
 +
 +
 +static void xen_relocator_hook(target_phys_addr_t *prot_addr_upd,
 +                               uint16_t protocol,
 +                             const uint8_t header[], int kernel_size,
 +                             target_phys_addr_t real_addr, int real_size)
 +{
 +    target_phys_addr_t prot_addr = *prot_addr_upd;
 +
 +    /* Urgh, Xen's HVM firmware lives at 0x100000, but that's also the
 +     * address Linux wants to start life at prior to relocatable support
 +     */
 +    fprintf(stderr, "checking need for relocation, header protocol: %x\n",
 +          protocol);
 +
 +    if (prot_addr != 0x10000) { /* old low kernels are OK */
 +      target_phys_addr_t reloc_prot_addr = 0x200000;
 +      
 +        if (protocol >= 0x205 && (header[0x234] & 1)) {
 +          /* Relocatable automatically */
 +          stl_phys(real_addr+0x214, reloc_prot_addr);
 +          fprintf(stderr, "qemu: kernel is relocatable\n");
 +      } else {
 +          /* Setup a helper which moves  kernel back to
 +           * its expected addr after firmware has got out
 +           * of the way. We put a helper at  reloc_prot_addr+kernel_size.
 +           * It moves kernel from reloc_prot_addr to prot_addr and
 +           * then jumps to prot_addr. Yes this is sick.
 +           */
 +          fprintf(stderr, "qemu: kernel is NOT relocatable\n");
 +          stl_phys(real_addr+0x214, reloc_prot_addr + kernel_size);
 +          setup_relocator(reloc_prot_addr + kernel_size, reloc_prot_addr, prot_addr, kernel_size);
 +      }
 +      fprintf(stderr, "qemu: loading kernel protected mode (%x bytes) at %#zx\n",
 +              kernel_size, (size_t)reloc_prot_addr);
 +      fprintf(stderr, "qemu: loading kernel real mode (%x bytes) at %#zx\n",
 +              real_size, (size_t)real_addr);
 +        *prot_addr_upd = reloc_prot_addr;
 +    }
 +}
 +
 +#ifdef CONFIG_DM
 +
 +void vmport_init(void) { }
 +int apic_init(CPUX86State *env) { return 0; }
 +
 +#endif /* CONFIG_DM */
diff --cc hw/pc.h
Simple merge
diff --cc hw/pci.c
Simple merge
diff --cc hw/pcnet.c
Simple merge
diff --cc hw/rtl8139.c
index 9ae76e641eede6210ec2932a25f3bba9a8ca76ff,cae8788586ae3d6f66c754ff58db07b364c3fc9a..c464d6f67ca20eed5f1ee1002e478b760478f3e5
@@@ -2016,12 -1998,12 +2016,12 @@@ static int rtl8139_cplus_transmit_one(R
          DEBUG_PRINT(("RTL8139: +++ C+ mode transmission buffer allocated space %d\n", s->cplus_txbuffer_len));
      }
  
 -    while (s->cplus_txbuffer && s->cplus_txbuffer_offset + txsize >= s->cplus_txbuffer_len)
 +    if (s->cplus_txbuffer && s->cplus_txbuffer_offset + txsize >= s->cplus_txbuffer_len)
      {
-       free(s->cplus_txbuffer);
-       s->cplus_txbuffer = NULL;
 -        s->cplus_txbuffer_len += CP_TX_BUFFER_SIZE;
 -        s->cplus_txbuffer = qemu_realloc(s->cplus_txbuffer, s->cplus_txbuffer_len);
++        free(s->cplus_txbuffer);
++        s->cplus_txbuffer = NULL;
  
-       DEBUG_PRINT(("RTL8139: +++ C+ mode transmission buffer space exceeded: %d\n", s->cplus_txbuffer_offset + txsize));
 -        DEBUG_PRINT(("RTL8139: +++ C+ mode transmission buffer space changed to %d\n", s->cplus_txbuffer_len));
++        DEBUG_PRINT(("RTL8139: +++ C+ mode transmission buffer space exceeded: %d\n", s->cplus_txbuffer_offset + txsize));
      }
  
      if (!s->cplus_txbuffer)
@@@ -3477,10 -3454,9 +3477,10 @@@ void pci_rtl8139_init(PCIBus *bus, NICI
      s->cplus_txbuffer_len = 0;
      s->cplus_txbuffer_offset = 0;
  
 -    register_savevm("rtl8139", -1, 3, rtl8139_save, rtl8139_load, s);
 +    instance = pci_bus_num(bus) << 8 | s->pci_dev->devfn;
 +    register_savevm("rtl8139", instance, 3, rtl8139_save, rtl8139_load, s);
  
- #if RTL8139_ONBOARD_TIMER
+ #ifdef RTL8139_ONBOARD_TIMER
      s->timer = qemu_new_timer(vm_clock, rtl8139_timer, s);
  
      qemu_mod_timer(s->timer,
diff --cc hw/scsi-disk.c
Simple merge
diff --cc hw/serial.c
Simple merge
diff --cc hw/usb-hid.c
index 89fa3d57e275c37a99ebb1aa9eadb3a841d9fcca,972543f2823283cfa4884357eba7d69bbebdf658..1c6bd09e520c1606e2140830b3a49213da213380
@@@ -78,6 -66,9 +78,8 @@@ typedef struct USBHIDState 
      int kind;
      int protocol;
      int idle;
 -    int changed;
+     void *datain_opaque;
+     void (*datain)(void *);
  } USBHIDState;
  
  /* mostly the same values as the Bochs USB Mouse device */
@@@ -413,56 -404,40 +415,64 @@@ static const uint8_t usb_hid_usage_keys
      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  };
  
 -static void usb_hid_changed(USBHIDState *hs)
++static void usb_notify_datain_cb(USBHIDState *hs)
+ {
 -    hs->changed = 1;
 -
+     if (hs->datain)
+         hs->datain(hs->datain_opaque);
+ }
 -static void usb_mouse_event(void *opaque,
 -                            int dx1, int dy1, int dz1, int buttons_state)
 -{
 -    USBHIDState *hs = opaque;
 -    USBMouseState *s = &hs->ptr;
 -
 -    s->dx += dx1;
 -    s->dy += dy1;
 -    s->dz += dz1;
 -    s->buttons_state = buttons_state;
 -
 -    usb_hid_changed(hs);
 +static void usb_pointer_event_clear(USBPointerEvent *e, int buttons) {
 +    e->xdx = e->ydy = e->dz = 0;
 +    e->buttons_state = buttons;
  }
  
 -static void usb_tablet_event(void *opaque,
 -                           int x, int y, int dz, int buttons_state)
 -{
 -    USBHIDState *hs = opaque;
 -    USBMouseState *s = &hs->ptr;
 +static void usb_pointer_event_combine(USBPointerEvent *e, int xyrel,
 +                                    int x1, int y1, int z1) {
 +    if (xyrel) {
 +      e->xdx += x1;
 +      e->ydy += y1;
 +    } else {
 +      e->xdx = x1;
 +      e->ydy = y1;
 +    }
 +    e->dz += z1;
 +}
  
 -    s->x = x;
 -    s->y = y;
 -    s->dz += dz;
 -    s->buttons_state = buttons_state;
 +static void usb_pointer_event(void *hs_v, int x1, int y1, int z1,
 +                            int buttons_state) {
 +    /* We combine events where feasible to keep the queue small.
 +     * We shouldn't combine anything with the first event with
 +     * a particular button state, as that would change the
 +     * location of the button state change. */
 +    USBHIDState *hs= hs_v;
 +    USBPointerState *s = &hs->ptr;
 +    unsigned use_slot= (s->tail-1) & QUEUEINDEXMASK;
 +    unsigned previous_slot= (use_slot-1) & QUEUEINDEXMASK;
 +
 +    if (s->tail == s->head) {
 +        use_slot= s->tail;
 +        QUEUE_INCR(s->tail);
 +        usb_pointer_event_clear(&s->queue[use_slot], buttons_state);
 +    } else if (use_slot == s->head ||
 +      s->queue[use_slot].buttons_state != buttons_state ||
 +      s->queue[previous_slot].buttons_state != buttons_state) {
 +      /* can't or shouldn't combine this event with previous one */
 +      use_slot= s->tail;
 +      QUEUE_INCR(s->tail);
 +      if (use_slot == s->head) {
 +          /* queue full, oh well, discard something */
 +          s->head++;  s->head &= QUEUEINDEXMASK;
 +          /* but we preserve the relative motions */
 +          usb_pointer_event_combine(&s->queue[s->head], s->xyrel,
 +                                    s->queue[use_slot].xdx,
 +                                    s->queue[use_slot].ydy,
 +                                    s->queue[use_slot].dz);
 +      }
 +      usb_pointer_event_clear(&s->queue[use_slot], buttons_state);
 +    }
 +    usb_pointer_event_combine(&s->queue[use_slot],s->xyrel, x1,y1,z1);
 -    usb_hid_changed(hs);
++    usb_notify_datain_cb(hs);
  }
  
  static void usb_keyboard_event(void *opaque, int keycode)
      hid_code = usb_hid_usage_keys[key | ((s->modifiers >> 1) & (1 << 7))];
      s->modifiers &= ~(1 << 8);
  
 +    s->changed = 1;
++    usb_notify_datain_cb(hs);
 +
      switch (hid_code) {
      case 0x00:
          return;
              if (s->key[i] == hid_code) {
                  s->key[i] = s->key[-- s->keys];
                  s->key[s->keys] = 0x00;
-                 return;
 -                usb_hid_changed(hs);
+                 break;
              }
+         if (i < 0)
+             return;
      } else {
          for (i = s->keys - 1; i >= 0; i --)
              if (s->key[i] == hid_code)
-                 return;
-         if (s->keys < sizeof(s->key))
-             s->key[s->keys ++] = hid_code;
+                 break;
+         if (i < 0) {
+             if (s->keys < sizeof(s->key))
+                 s->key[s->keys ++] = hid_code;
+         } else
+             return;
      }
 -
 -    usb_hid_changed(hs);
  }
  
  static inline int int_clamp(int val, int vmin, int vmax)
@@@ -544,69 -515,68 +560,72 @@@ static int usb_pointer_poll(USBHIDStat
        s->mouse_grabbed = 1;
      }
  
 -    dx = int_clamp(s->dx, -127, 127);
 -    dy = int_clamp(s->dy, -127, 127);
 -    dz = int_clamp(s->dz, -127, 127);
 +    if (s->head == s->tail)
 +        /* use the last report */
 +        s->head = (s->head - 1) & QUEUEINDEXMASK;
 +
 +    e = &s->queue[s->head];
  
-     dz = int_clamp(e->dz, -127, 127);
 -    s->dx -= dx;
 -    s->dy -= dy;
 -    s->dz -= dz;
++    dz = int_clamp(e->dz, -128, 127);
  
-         dx = int_clamp(e->xdx, -127, 127);
-         dy = int_clamp(e->ydy, -127, 127);
 +    if (s->xyrel) {
++        dx = int_clamp(e->xdx, -128, 127);
++        dy = int_clamp(e->ydy, -128, 127);
 +      e->xdx -= dx;
 +      e->ydy -= dy;
 +    } else {
 +        dx = e->xdx;
 +        dy = e->ydy;
 +    }
      /* Appears we have to invert the wheel direction */
      dz = 0 - dz;
  
 -    b = 0;
 -    if (s->buttons_state & MOUSE_EVENT_LBUTTON)
 -        b |= 0x01;
 -    if (s->buttons_state & MOUSE_EVENT_RBUTTON)
 -        b |= 0x02;
 -    if (s->buttons_state & MOUSE_EVENT_MBUTTON)
 -        b |= 0x04;
 -
 -    l = 0;
 -    if (len > l)
 -        buf[l ++] = b;
 -    if (len > l)
 -        buf[l ++] = dx;
 -    if (len > l)
 -        buf[l ++] = dy;
 -    if (len > l)
 -        buf[l ++] = dz;
 -    return l;
 -}
 -
 -static int usb_tablet_poll(USBHIDState *hs, uint8_t *buf, int len)
 -{
 -    int dz, b, l;
 -    USBMouseState *s = &hs->ptr;
 -
 -    if (!s->mouse_grabbed) {
 -      s->eh_entry = qemu_add_mouse_event_handler(usb_tablet_event, hs,
 -                                                  1, "QEMU USB Tablet");
 -      s->mouse_grabbed = 1;
 +    if (!(e->dz ||
 +        (s->xyrel && (e->xdx || e->ydy)))) {
 +      /* that deals with this event */
 +      QUEUE_INCR(s->head);
      }
  
 -    dz = int_clamp(s->dz, -127, 127);
 -    s->dz -= dz;
 -
+     /* Appears we have to invert the wheel direction */
+     dz = 0 - dz;
++
      b = 0;
 -    if (s->buttons_state & MOUSE_EVENT_LBUTTON)
 +    if (e->buttons_state & MOUSE_EVENT_LBUTTON)
          b |= 0x01;
 -    if (s->buttons_state & MOUSE_EVENT_RBUTTON)
 +    if (e->buttons_state & MOUSE_EVENT_RBUTTON)
          b |= 0x02;
 -    if (s->buttons_state & MOUSE_EVENT_MBUTTON)
 +    if (e->buttons_state & MOUSE_EVENT_MBUTTON)
          b |= 0x04;
  
 -    buf[0] = b;
 -    buf[1] = s->x & 0xff;
 -    buf[2] = s->x >> 8;
 -    buf[3] = s->y & 0xff;
 -    buf[4] = s->y >> 8;
 -    buf[5] = dz;
 -    l = 6;
 +    switch (hs->kind) {
 +    case USB_MOUSE:
 +      l = 0;
 +      if (len > l)
 +          buf[l ++] = b;
 +      if (len > l)
 +          buf[l ++] = dx;
 +      if (len > l)
 +          buf[l ++] = dy;
 +      if (len > l)
 +          buf[l ++] = dz;
 +      break;
 +
 +    case USB_TABLET:
 +      /* Appears we have to invert the wheel direction */
 +      dz = 0 - dz;
 +
 +      buf[0] = b;
 +      buf[1] = dx & 0xff;
 +      buf[2] = dx >> 8;
 +      buf[3] = dy & 0xff;
 +      buf[4] = dy >> 8;
 +      buf[5] = dz;
 +      l = 6;
 +      break;
 +
 +    default:
 +      abort();
 +    }
  
      return l;
  }
diff --cc hw/usb-uhci.c
index 80581d9f04031f073ad583e1fa465dc443679b3a,b90cf78c11169a42e39d21fc42c8a46bd8369e39..efa6b5231186e866e0085caba9f936e0b3c0af68
@@@ -529,152 -685,277 +685,284 @@@ static int uhci_complete_td(UHCIState *
      max_len = ((td->token >> 21) + 1) & 0x7ff;
      pid = td->token & 0xff;
  
-     if (completion && (s->async_qh || s->async_frame_addr)) {
-         ret = s->usb_packet.len;
-         if (ret >= 0) {
-             len = ret;
-             if (len > max_len) {
-                 len = max_len;
-                 ret = USB_RET_BABBLE;
-             }
-             if (len > 0) {
-                 /* write the data back */
-                 cpu_physical_memory_write(td->buffer, s->usb_buf, len);
-             }
-         } else {
-             len = 0;
-         }
-         s->async_qh = 0;
-         s->async_frame_addr = 0;
-     } else if (!completion) {
-         s->usb_packet.pid = pid;
-         s->usb_packet.devaddr = (td->token >> 8) & 0x7f;
-         s->usb_packet.devep = (td->token >> 15) & 0xf;
-         s->usb_packet.data = s->usb_buf;
-         s->usb_packet.len = max_len;
-         s->usb_packet.complete_cb = uhci_async_complete_packet;
-         s->usb_packet.complete_opaque = s;
-         switch(pid) {
-         case USB_TOKEN_OUT:
-         case USB_TOKEN_SETUP:
-             cpu_physical_memory_read(td->buffer, s->usb_buf, max_len);
-             ret = uhci_broadcast_packet(s, &s->usb_packet);
-             len = max_len;
-             break;
-         case USB_TOKEN_IN:
-             ret = uhci_broadcast_packet(s, &s->usb_packet);
-             if (ret >= 0) {
-                 len = ret;
-                 if (len > max_len) {
-                     len = max_len;
-                     ret = USB_RET_BABBLE;
-                 }
-                 if (len > 0) {
-                     /* write the data back */
-                     cpu_physical_memory_write(td->buffer, s->usb_buf, len);
-                 }
-             } else {
-                 len = 0;
-             }
-             break;
-         default:
-             /* invalid pid : frame interrupted */
-             s->status |= UHCI_STS_HCPERR;
-             uhci_update_irq(s);
-             ret = -1;
-           goto out;
-         }
-     }
+     ret = async->packet.len;
  
-     if (ret == USB_RET_ASYNC) {
-         return 2;
-     }
 -    if (td->ctrl & TD_CTRL_IOC)
 -        *int_mask |= 0x01;
 -
      if (td->ctrl & TD_CTRL_IOS)
          td->ctrl &= ~TD_CTRL_ACTIVE;
-     if (ret >= 0) {
-         td->ctrl = (td->ctrl & ~0x7ff) | ((len - 1) & 0x7ff);
-         /* The NAK bit may have been set by a previous frame, so clear it
-            here.  The docs are somewhat unclear, but win2k relies on this
-            behavior.  */
-         td->ctrl &= ~(TD_CTRL_ACTIVE | TD_CTRL_NAK);
-         if (pid == USB_TOKEN_IN &&
-             (td->ctrl & TD_CTRL_SPD) &&
-             len < max_len) {
+     if (ret < 0)
+         goto out;
+     len = async->packet.len;
+     td->ctrl = (td->ctrl & ~0x7ff) | ((len - 1) & 0x7ff);
+     /* The NAK bit may have been set by a previous frame, so clear it
+        here.  The docs are somewhat unclear, but win2k relies on this
+        behavior.  */
+     td->ctrl &= ~(TD_CTRL_ACTIVE | TD_CTRL_NAK);
+     if (pid == USB_TOKEN_IN) {
+         if (len > max_len) {
+             len = max_len;
+             ret = USB_RET_BABBLE;
+             goto out;
+         }
+         if (len > 0) {
+             /* write the data back */
+             cpu_physical_memory_write(td->buffer, async->buffer, len);
+         }
+         if ((td->ctrl & TD_CTRL_SPD) && len < max_len) {
              *int_mask |= 0x02;
              /* short packet: do not update QH */
 -            return 1;
+             dprintf("uhci: short packet. td 0x%x token 0x%x\n", async->td, async->token);
-             goto out;
-         } else {
-             /* success */
-             ret = 0;
-             goto out;
 +            ret = 1;
++          goto out_update_ioc;
          }
-     } else {
-         switch(ret) {
-         default:
-         case USB_RET_NODEV:
-         do_timeout:
-             td->ctrl |= TD_CTRL_TIMEOUT;
-             err = (td->ctrl >> TD_CTRL_ERROR_SHIFT) & 3;
-             if (err != 0) {
-                 err--;
-                 if (err == 0) {
-                     td->ctrl &= ~TD_CTRL_ACTIVE;
-                     s->status |= UHCI_STS_USBERR;
-                     uhci_update_irq(s);
-                 }
-             }
-             td->ctrl = (td->ctrl & ~(3 << TD_CTRL_ERROR_SHIFT)) |
-                 (err << TD_CTRL_ERROR_SHIFT);
-             ret = 1;
-             goto out;
-         case USB_RET_NAK:
-             td->ctrl |= TD_CTRL_NAK;
-             if (pid == USB_TOKEN_SETUP)
-                 goto do_timeout;
-             ret = 1;
-             goto out;
-         case USB_RET_STALL:
-             td->ctrl |= TD_CTRL_STALL;
-             td->ctrl &= ~TD_CTRL_ACTIVE;
-             ret = 1;
-             goto out;
-         case USB_RET_BABBLE:
-             td->ctrl |= TD_CTRL_BABBLE | TD_CTRL_STALL;
+     }
+     /* success */
 -    return 0;
++    ret = 0;
++    goto out_update_ioc;
+ out:
+     switch(ret) {
+     case USB_RET_STALL:
+         td->ctrl |= TD_CTRL_STALL;
+         td->ctrl &= ~TD_CTRL_ACTIVE;
 -        return 1;
++        ret = 1;
++        goto out_update_ioc;
+     case USB_RET_BABBLE:
+         td->ctrl |= TD_CTRL_BABBLE | TD_CTRL_STALL;
+         td->ctrl &= ~TD_CTRL_ACTIVE;
+         /* frame interrupted */
 -        return -1;
++        ret = -1;
++        goto out_update_ioc;
+     case USB_RET_NAK:
+         td->ctrl |= TD_CTRL_NAK;
+         if (pid == USB_TOKEN_SETUP)
+             break;
 -      return 1;
++      ret = 1;
++        goto out_update_ioc;
+     case USB_RET_NODEV:
+     default:
+       break;
+     }
+     /* Retry the TD if error count is not zero */
+     td->ctrl |= TD_CTRL_TIMEOUT;
+     err = (td->ctrl >> TD_CTRL_ERROR_SHIFT) & 3;
+     if (err != 0) {
+         err--;
+         if (err == 0) {
              td->ctrl &= ~TD_CTRL_ACTIVE;
-             /* frame interrupted */
-             ret = -1;
-             goto out;
+             s->status |= UHCI_STS_USBERR;
+             uhci_update_irq(s);
          }
      }
-    
- out:
-     /* If TD is inactive and IOC bit set to 1 then update int_mask */ 
-     if ((td->ctrl & TD_CTRL_IOC) && (!(td->ctrl & TD_CTRL_ACTIVE))) {
+     td->ctrl = (td->ctrl & ~(3 << TD_CTRL_ERROR_SHIFT)) |
+         (err << TD_CTRL_ERROR_SHIFT);
 -    return 1;
++    ret = 1;
++
++ out_update_ioc:
++    if ((td->ctrl & TD_CTRL_IOC) && !(td->ctrl &= ~TD_CTRL_ACTIVE))
 +        *int_mask |= 0x01;
-     }
 +    return ret;
  }
  
- static void uhci_async_complete_packet(USBPacket * packet, void *opaque)
+ static int uhci_handle_td(UHCIState *s, uint32_t addr, UHCI_TD *td, uint32_t *int_mask)
+ {
+     UHCIAsync *async;
+     int len = 0, max_len;
+     uint8_t pid;
+     /* Is active ? */
+     if (!(td->ctrl & TD_CTRL_ACTIVE))
+         return 1;
+     async = uhci_async_find_td(s, addr, td->token);
+     if (async) {
+         /* Already submitted */
+         async->valid = 32;
+         if (!async->done)
+             return 1;
+         uhci_async_unlink(s, async);
+         goto done;
+     }
+     /* Allocate new packet */
+     async = uhci_async_alloc(s);
+     if (!async)
+         return 1;
+     async->valid = 10;
+     async->td    = addr;
+     async->token = td->token;
+     max_len = ((td->token >> 21) + 1) & 0x7ff;
+     pid = td->token & 0xff;
+     async->packet.pid     = pid;
+     async->packet.devaddr = (td->token >> 8) & 0x7f;
+     async->packet.devep   = (td->token >> 15) & 0xf;
+     async->packet.data    = async->buffer;
+     async->packet.len     = max_len;
+     async->packet.complete_cb     = uhci_async_complete;
+     async->packet.complete_opaque = s;
+     switch(pid) {
+     case USB_TOKEN_OUT:
+     case USB_TOKEN_SETUP:
+         cpu_physical_memory_read(td->buffer, async->buffer, max_len);
+         len = uhci_broadcast_packet(s, &async->packet);
+         if (len >= 0)
+             len = max_len;
+         break;
+     case USB_TOKEN_IN:
+         len = uhci_broadcast_packet(s, &async->packet);
+         break;
+     default:
+         /* invalid pid : frame interrupted */
+         uhci_async_free(s, async);
+         s->status |= UHCI_STS_HCPERR;
+         uhci_update_irq(s);
+         return -1;
+     }
+  
+     if (len == USB_RET_ASYNC) {
+         uhci_async_link(s, async);
+         return 2;
+     }
+     async->packet.len = len;
+ done:
+     len = uhci_complete_td(s, td, async, int_mask);
+     uhci_async_free(s, async);
+     return len;
+ }
+ static void uhci_async_complete(USBPacket *packet, void *opaque)
  {
      UHCIState *s = opaque;
-     UHCI_QH qh;
+     UHCIAsync *async = (UHCIAsync *) packet;
+     dprintf("uhci: async complete. td 0x%x token 0x%x\n", async->td, async->token);
+     async->done = 1;
+     uhci_process_frame(s);
+ }
+ static int is_valid(uint32_t link)
+ {
+     return (link & 1) == 0;
+ }
+ static int is_qh(uint32_t link)
+ {
+     return (link & 2) != 0;
+ }
+ static int depth_first(uint32_t link)
+ {
+     return (link & 4) != 0;
+ }
+ /* QH DB used for detecting QH loops */
+ #define UHCI_MAX_QUEUES 128
+ typedef struct {
+     uint32_t addr[UHCI_MAX_QUEUES];
+     int      count;
+ } QhDb;
+ static void qhdb_reset(QhDb *db)
+ {
+     db->count = 0;
+ }
+ /* Add QH to DB. Returns 1 if already present or DB is full. */
+ static int qhdb_insert(QhDb *db, uint32_t addr)
+ {
+     int i;
+     for (i = 0; i < db->count; i++)
+         if (db->addr[i] == addr)
+             return 1;
+     if (db->count >= UHCI_MAX_QUEUES)
+         return 1;
+     db->addr[db->count++] = addr;
+     return 0;
+ }
+ static void uhci_process_frame(UHCIState *s)
+ {
+     uint32_t frame_addr, link, old_td_ctrl, val, int_mask;
+     uint32_t curr_qh;
+     int cnt, ret;
      UHCI_TD td;
-     uint32_t link;
-     uint32_t old_td_ctrl;
-     uint32_t val;
-     uint32_t frame_addr;
-     int ret;
+     UHCI_QH qh;
+     QhDb qhdb;
+     frame_addr = s->fl_base_addr + ((s->frnum & 0x3ff) << 2);
+     dprintf("uhci: processing frame %d addr 0x%x\n" , s->frnum, frame_addr);
+     cpu_physical_memory_read(frame_addr, (uint8_t *)&link, 4);
+     le32_to_cpus(&link);
+     int_mask = 0;
+     curr_qh  = 0;
+     qhdb_reset(&qhdb);
+     for (cnt = FRAME_MAX_LOOPS; is_valid(link) && cnt; cnt--) {
+         if (is_qh(link)) {
+             /* QH */
+             if (qhdb_insert(&qhdb, link)) {
+                 /*
+                  * We're going in circles. Which is not a bug because
+                  * HCD is allowed to do that as part of the BW management. 
+                  * In our case though it makes no sense to spin here. Sync transations 
+                  * are already done, and async completion handler will re-process 
+                  * the frame when something is ready.
+                  */
+                 dprintf("uhci: detected loop. qh 0x%x\n", link);
+                 break;
+             }
+             cpu_physical_memory_read(link & ~0xf, (uint8_t *) &qh, sizeof(qh));
+             le32_to_cpus(&qh.link);
+             le32_to_cpus(&qh.el_link);
  
-     /* Handle async isochronous packet completion */
-     frame_addr = s->async_frame_addr;
-     if (frame_addr) {
-         cpu_physical_memory_read(frame_addr, (uint8_t *)&link, 4);
-         le32_to_cpus(&link);
+             dprintf("uhci: QH 0x%x load. link 0x%x elink 0x%x\n",
+                     link, qh.link, qh.el_link);
  
-         cpu_physical_memory_read(link & ~0xf, (uint8_t *)&td, sizeof(td));
+             if (!is_valid(qh.el_link)) {
+                 /* QH w/o elements */
+                 curr_qh = 0;
+                 link = qh.link;
+             } else {
+                 /* QH with elements */
+               curr_qh = link;
+               link = qh.el_link;
+             }
+             continue;
+         }
+         /* TD */
+         cpu_physical_memory_read(link & ~0xf, (uint8_t *) &td, sizeof(td));
          le32_to_cpus(&td.link);
          le32_to_cpus(&td.ctrl);
          le32_to_cpus(&td.token);
diff --cc hw/usb.h
Simple merge
diff --cc hw/vga.c
index 8e5a2c1768fa6bbebcb40851093ce83699c403d3,19a9b4ac125c54f0b7fdfbe1f4df06d1e62dc035..5e677900e415f7257646d53d70a1872ba003e9a0
+++ b/hw/vga.c
  #include "pc.h"
  #include "pci.h"
  #include "vga_int.h"
 -#include "pixel_ops.h"
++//<<<<<<< HEAD/hw/vga.c
 +#include <sys/mman.h>
 +#include "sysemu.h"
 +#include "qemu-xen.h"
 +#include "exec-all.h"
++//=======
++//#include "pixel_ops.h"
+ #include "qemu-timer.h"
++//>>>>>>> 3df1a17b0ab8a8be4e3c9d6b2fa0812c652520f1/hw/vga.c
  
  //#define DEBUG_VGA
  //#define DEBUG_VGA_MEM
@@@ -2157,10 -2143,22 +2503,22 @@@ void vga_common_init(VGAState *s, Displ
      s->get_bpp = vga_get_bpp;
      s->get_offsets = vga_get_offsets;
      s->get_resolution = vga_get_resolution;
 -    s->update = vga_update_display;
 -    s->invalidate = vga_invalidate_display;
 -    s->screen_dump = vga_screen_dump;
 -    s->text_update = vga_update_text;
 +    graphic_console_init(s->ds, vga_update_display, vga_invalidate_display,
-                          vga_screen_dump, NULL, s);
++                         vga_screen_dump, vga_update_text, s);
 +
 +    vga_bios_init(s);
+     switch (vga_retrace_method) {
+     case VGA_RETRACE_DUMB:
+         s->retrace = vga_dumb_retrace;
+         s->update_retrace_info = vga_dumb_update_retrace_info;
+         break;
+     case VGA_RETRACE_PRECISE:
+         s->retrace = vga_precise_retrace;
+         s->update_retrace_info = vga_precise_update_retrace_info;
+         memset(&s->retrace_info, 0, sizeof (s->retrace_info));
+         break;
+     }
  }
  
  /* used by both ISA and PCI */
diff --cc hw/vga_int.h
index 188a7553c70f5fc0e3c7d84675c799e3d5cc555a,82a755ebfe92d2e5185c1e0f5bf6f93be77fb0fd..859316990b99f481f77c13c7a9e71d28284e451e
  #define CH_ATTR_SIZE (160 * 100)
  #define VGA_MAX_HEIGHT 2048
  
+ struct vga_precise_retrace {
+     int64_t ticks_per_char;
+     int64_t total_chars;
+     int htotal;
+     int hstart;
+     int hend;
+     int vstart;
+     int vend;
+     int freq;
+ };
+ union vga_retrace {
+     struct vga_precise_retrace precise;
+ };
+ struct VGAState;
+ typedef uint8_t (* vga_retrace_fn)(struct VGAState *s);
+ typedef void (* vga_update_retrace_info_fn)(struct VGAState *s);
  #define VGA_STATE_COMMON                                                \
      uint8_t *vram_ptr;                                                  \
 +    xen_pfn_t *vram_mfns;                                               \
 +    uint64_t stolen_vram_addr; /* Address of stolen RAM */              \
      unsigned long vram_offset;                                          \
      unsigned int vram_size;                                             \
      unsigned long bios_offset;                                          \
diff --cc hw/vmware_vga.c
Simple merge
diff --cc i386-dm/cpu.h
index 1ba351befe974ae6e96459e40bb8701c9db3da8d,0000000000000000000000000000000000000000..cba811535cde7465a7a81052b0609f2904c49737
mode 100644,000000..100644
--- /dev/null
@@@ -1,123 -1,0 +1,121 @@@
-     int interrupt_request;
 +/*
 + * i386 virtual CPU header
 + * 
 + *  Copyright (c) 2003 Fabrice Bellard
 + *
 + * This library is free software; you can redistribute it and/or
 + * modify it under the terms of the GNU Lesser General Public
 + * License as published by the Free Software Foundation; either
 + * version 2 of the License, or (at your option) any later version.
 + *
 + * This library is distributed in the hope that it will be useful,
 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 + * Lesser General Public License for more details.
 + *
 + * You should have received a copy of the GNU Lesser General Public
 + * License along with this library; if not, write to the Free Software
 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 + */
 +#ifndef CPU_I386_H
 +#define CPU_I386_H
 +
 +#include "config.h"
 +
 +struct CPUX86State;
 +
 +#ifdef TARGET_X86_64
 +#define TARGET_LONG_BITS 64
 +#else
 +/* #define TARGET_LONG_BITS 32 */
 +#define TARGET_LONG_BITS 64 /* for Qemu map cache */
 +#endif
 +
 +/* target supports implicit self modifying code */
 +#define TARGET_HAS_SMC
 +/* support for self modifying code even if the modified instruction is
 +   close to the modifying instruction */
 +#define TARGET_HAS_PRECISE_SMC
 +
 +/* MMU modes definitions
 + */
 +/* We aren't handling the MMU in Qemu; all the addresses we deal with
 + * are guest physical.  So as far as qemu
 + * is concerned there is only the one MMU mode.
 + */
 +#define NB_MMU_MODES 1
 +#define MMU_MODE0_SUFFIX _xen
 +static inline int cpu_mmu_index(struct CPUX86State *env) { return 0; }
 +
 +#include "cpu-defs.h"
 +
 +#ifdef CONFIG_SOFTFLOAT
 +#include "softfloat.h"
 +#endif
 +
 +#if defined(__i386__) && !defined(CONFIG_SOFTMMU)
 +#define USE_CODE_COPY
 +#endif
 +
 +#ifdef CONFIG_SOFTFLOAT
 +#ifdef USE_X86LDOUBLE
 +typedef floatx80 CPU86_LDouble;
 +#else
 +typedef float64 CPU86_LDouble;
 +#endif
 +#endif
 +
 +typedef struct SegmentCache {
 +    uint32_t selector;
 +    target_ulong base;
 +    uint32_t limit;
 +    uint32_t flags;
 +} SegmentCache;
 +
 +/* Empty for now */
 +typedef struct CPUX86State {
 +    uint32_t a20_mask;
 +
 +    CPU_COMMON
 +} CPUX86State;
 +
 +CPUX86State *cpu_x86_init(const char *cpu_model);
 +int cpu_x86_exec(CPUX86State *s);
 +void cpu_x86_close(CPUX86State *s);
 +int cpu_get_pic_interrupt(CPUX86State *s);
 +/* MSDOS compatibility mode FPU exception support */
 +void cpu_set_ferr(CPUX86State *s);
 +
 +void cpu_x86_set_a20(CPUX86State *env, int a20_state);
 +
 +/* used to debug */
 +#define X86_DUMP_FPU  0x0001 /* dump FPU state too */
 +#define X86_DUMP_CCOP 0x0002 /* dump qemu flag cache */
 +
 +#ifndef IN_OP_I386
 +void cpu_x86_outb(CPUX86State *env, int addr, int val);
 +void cpu_x86_outw(CPUX86State *env, int addr, int val);
 +void cpu_x86_outl(CPUX86State *env, int addr, int val);
 +int cpu_x86_inb(CPUX86State *env, int addr);
 +int cpu_x86_inw(CPUX86State *env, int addr);
 +int cpu_x86_inl(CPUX86State *env, int addr);
 +#endif
 +
 +/* helper2.c */
 +int main_loop(void);
 +
 +#if defined(__i386__) || defined(__x86_64__)
 +#define TARGET_PAGE_BITS 12
 +#elif defined(__ia64__)
 +#define TARGET_PAGE_BITS 14
 +#endif 
 +
 +#define CPUState CPUX86State
 +#define cpu_init cpu_x86_init
 +#define cpu_exec cpu_x86_exec
 +#define cpu_gen_code cpu_x86_gen_code
 +#define cpu_signal_handler cpu_x86_signal_handler
 +
 +#include "cpu-all.h"
 +
 +#endif /* CPU_I386_H */
index dec4aa8b28e25e59babc99b9ea1a55e86383117d,0000000000000000000000000000000000000000..6dbd4607abbf62dd49185aa2f0694ae2526ec0d3
mode 100644,000000..100644
--- /dev/null
@@@ -1,699 -1,0 +1,704 @@@
- ram_addr_t ram_size;
 +/*
 + *  virtual page mapping and translated block handling
 + * 
 + *  Copyright (c) 2003 Fabrice Bellard
 + *
 + * This library is free software; you can redistribute it and/or
 + * modify it under the terms of the GNU Lesser General Public
 + * License as published by the Free Software Foundation; either
 + * version 2 of the License, or (at your option) any later version.
 + *
 + * This library is distributed in the hope that it will be useful,
 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 + * Lesser General Public License for more details.
 + *
 + * You should have received a copy of the GNU Lesser General Public
 + * License along with this library; if not, write to the Free Software
 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 + */
 +#include "config.h"
 +#ifdef _WIN32
 +#include <windows.h>
 +#else
 +#include <sys/types.h>
 +#include <sys/mman.h>
 +#endif
 +#include <stdlib.h>
 +#include <stdio.h>
 +#include <stdarg.h>
 +#include <string.h>
 +#include <errno.h>
 +#include <unistd.h>
 +#include <inttypes.h>
 +
 +#include "cpu.h"
 +#include "exec-all.h"
 +#include "hw.h"
 +#include "qemu-xen.h"
 +
 +//#define DEBUG_TB_INVALIDATE
 +//#define DEBUG_FLUSH
 +//#define DEBUG_TLB
 +
 +/* make various TB consistency checks */
 +//#define DEBUG_TB_CHECK 
 +//#define DEBUG_TLB_CHECK 
 +
 +#ifndef CONFIG_DM
 +/* threshold to flush the translated code buffer */
 +#define CODE_GEN_BUFFER_MAX_SIZE (CODE_GEN_BUFFER_SIZE - CODE_GEN_MAX_SIZE)
 +
 +#define SMC_BITMAP_USE_THRESHOLD 10
 +
 +#define MMAP_AREA_START        0x00000000
 +#define MMAP_AREA_END          0xa8000000
 +
 +TranslationBlock tbs[CODE_GEN_MAX_BLOCKS];
 +TranslationBlock *tb_hash[CODE_GEN_HASH_SIZE];
 +TranslationBlock *tb_phys_hash[CODE_GEN_PHYS_HASH_SIZE];
 +int nb_tbs;
 +/* any access to the tbs or the page table must use this lock */
 +spinlock_t tb_lock = SPIN_LOCK_UNLOCKED;
 +
 +uint8_t code_gen_buffer[CODE_GEN_BUFFER_SIZE];
 +uint8_t *code_gen_ptr;
 +#endif /* !CONFIG_DM */
 +
++int use_icount = 0;
++int64_t qemu_icount;
 +ram_addr_t phys_ram_size;
- CPULogItem cpu_log_items[] = {
 +int phys_ram_fd;
 +uint8_t *phys_ram_base;
 +uint8_t *phys_ram_dirty;
 +
 +CPUState *first_cpu;
 +/* current CPU in the current thread. It is only valid inside
 +   cpu_exec() */
 +CPUState *cpu_single_env; 
 +
 +typedef struct PageDesc {
 +    /* list of TBs intersecting this ram page */
 +    TranslationBlock *first_tb;
 +    /* in order to optimize self modifying code, we count the number
 +       of lookups we do to a given page to use a bitmap */
 +    unsigned int code_write_count;
 +    uint8_t *code_bitmap;
 +#if defined(CONFIG_USER_ONLY)
 +    unsigned long flags;
 +#endif
 +} PageDesc;
 +
 +typedef struct PhysPageDesc {
 +    /* offset in host memory of the page + io_index in the low 12 bits */
 +    unsigned long phys_offset;
 +} PhysPageDesc;
 +
 +typedef struct VirtPageDesc {
 +    /* physical address of code page. It is valid only if 'valid_tag'
 +       matches 'virt_valid_tag' */ 
 +    target_ulong phys_addr; 
 +    unsigned int valid_tag;
 +#if !defined(CONFIG_SOFTMMU)
 +    /* original page access rights. It is valid only if 'valid_tag'
 +       matches 'virt_valid_tag' */
 +    unsigned int prot;
 +#endif
 +} VirtPageDesc;
 +
 +#define L2_BITS 10
 +#define L1_BITS (32 - L2_BITS - TARGET_PAGE_BITS)
 +
 +#define L1_SIZE (1 << L1_BITS)
 +#define L2_SIZE (1 << L2_BITS)
 +
 +unsigned long qemu_real_host_page_size;
 +unsigned long qemu_host_page_bits;
 +unsigned long qemu_host_page_size;
 +unsigned long qemu_host_page_mask;
 +
 +/* io memory support */
 +CPUWriteMemoryFunc *io_mem_write[IO_MEM_NB_ENTRIES][4];
 +CPUReadMemoryFunc *io_mem_read[IO_MEM_NB_ENTRIES][4];
 +void *io_mem_opaque[IO_MEM_NB_ENTRIES];
 +static int io_mem_nb = 1;
 +
 +/* log support */
 +FILE *logfile;
 +int loglevel;
 +
++void cpu_exec_init_all(unsigned long tb_size)
++{
++}
++
 +void cpu_exec_init(CPUState *env)
 +{
 +    CPUState **penv;
 +    int cpu_index;
 +
 +    env->next_cpu = NULL;
 +    penv = &first_cpu;
 +    cpu_index = 0;
 +    while (*penv != NULL) {
 +        penv = (CPUState **)&(*penv)->next_cpu;
 +        cpu_index++;
 +    }
 +    env->cpu_index = cpu_index;
 +    *penv = env;
 +
 +    /* alloc dirty bits array */
 +    phys_ram_dirty = qemu_malloc(phys_ram_size >> TARGET_PAGE_BITS);
 +}
 +
 +/* enable or disable low levels log */
 +void cpu_set_log(int log_flags)
 +{
 +    loglevel = log_flags;
 +    if (!logfile)
 +      logfile = stderr;
 +}
 +
 +void cpu_set_log_filename(const char *filename)
 +{
 +    logfile = fopen(filename, "w");
 +    if (!logfile) {
 +        perror(filename);
 +      _exit(1);
 +    }
 +#if !defined(CONFIG_SOFTMMU)
 +    /* must avoid mmap() usage of glibc by setting a buffer "by hand" */
 +    {
 +        static uint8_t logfile_buf[4096];
 +      setvbuf(logfile, logfile_buf, _IOLBF, sizeof(logfile_buf));
 +    }
 +#else
 +    setvbuf(logfile, NULL, _IOLBF, 0);
 +#endif
 +    dup2(fileno(logfile), 1);
 +    dup2(fileno(logfile), 2);
 +}
 +
 +/* mask must never be zero, except for A20 change call */
 +void cpu_interrupt(CPUState *env, int mask)
 +{
 +    env->interrupt_request |= mask;
 +}
 +
 +void cpu_reset_interrupt(CPUState *env, int mask)
 +{
 +    env->interrupt_request &= ~mask;
 +}
 +
-     CPULogItem *item;
++const CPULogItem cpu_log_items[] = {
 +    { CPU_LOG_TB_OUT_ASM, "out_asm", 
 +      "show generated host assembly code for each compiled TB" },
 +    { CPU_LOG_TB_IN_ASM, "in_asm",
 +      "show target assembly code for each compiled TB" },
 +    { CPU_LOG_TB_OP, "op", 
 +      "show micro ops for each compiled TB (only usable if 'in_asm' used)" },
 +#ifdef TARGET_I386
 +    { CPU_LOG_TB_OP_OPT, "op_opt",
 +      "show micro ops after optimization for each compiled TB" },
 +#endif
 +    { CPU_LOG_INT, "int",
 +      "show interrupts/exceptions in short format" },
 +    { CPU_LOG_EXEC, "exec",
 +      "show trace before each executed TB (lots of logs)" },
 +    { CPU_LOG_TB_CPU, "cpu",
 +      "show CPU state before bloc translation" },
 +#ifdef TARGET_I386
 +    { CPU_LOG_PCALL, "pcall",
 +      "show protected mode far calls/returns/exceptions" },
 +#endif
 +#ifdef DEBUG_IOPORT
 +    { CPU_LOG_IOPORT, "ioport",
 +      "show all i/o ports accesses" },
 +#endif
 +    { 0, NULL, NULL },
 +};
 +
 +static int cmp1(const char *s1, int n, const char *s2)
 +{
 +    if (strlen(s2) != n)
 +        return 0;
 +    return memcmp(s1, s2, n) == 0;
 +}
 +      
 +/* takes a comma separated list of log masks. Return 0 if error. */
 +int cpu_str_to_log_mask(const char *str)
 +{
++    const CPULogItem *item;
 +    int mask;
 +    const char *p, *p1;
 +
 +    p = str;
 +    mask = 0;
 +    for(;;) {
 +        p1 = strchr(p, ',');
 +        if (!p1)
 +            p1 = p + strlen(p);
 +      if(cmp1(p,p1-p,"all")) {
 +              for(item = cpu_log_items; item->mask != 0; item++) {
 +                      mask |= item->mask;
 +              }
 +      } else {
 +        for(item = cpu_log_items; item->mask != 0; item++) {
 +            if (cmp1(p, p1 - p, item->name))
 +                goto found;
 +        }
 +        return 0;
 +      }
 +    found:
 +        mask |= item->mask;
 +        if (*p1 != ',')
 +            break;
 +        p = p1 + 1;
 +    }
 +    return mask;
 +}
 +
 +void cpu_abort(CPUState *env, const char *fmt, ...)
 +{
 +    va_list ap;
 +
 +    va_start(ap, fmt);
 +    fprintf(stderr, "qemu: fatal: ");
 +    vfprintf(stderr, fmt, ap);
 +    fprintf(stderr, "\n");
 +    va_end(ap);
 +    abort();
 +}
 +
 +
 +/* XXX: Simple implementation. Fix later */
 +#define MAX_MMIO 32
 +struct mmio_space {
 +        target_phys_addr_t start;
 +        unsigned long size;
 +        unsigned long io_index;
 +} mmio[MAX_MMIO];
 +unsigned long mmio_cnt;
 +
 +/* register physical memory. 'size' must be a multiple of the target
 +   page size. If (phys_offset & ~TARGET_PAGE_MASK) != 0, then it is an
 +   io memory page */
 +void cpu_register_physical_memory(target_phys_addr_t start_addr, 
 +                                  unsigned long size,
 +                                  unsigned long phys_offset)
 +{
 +    int i;
 +
 +    for (i = 0; i < mmio_cnt; i++) { 
 +        if(mmio[i].start == start_addr) {
 +            mmio[i].io_index = phys_offset;
 +            mmio[i].size = size;
 +            return;
 +        }
 +    }
 +
 +    if (mmio_cnt == MAX_MMIO) {
 +        fprintf(logfile, "too many mmio regions\n");
 +        exit(-1);
 +    }
 +
 +    mmio[mmio_cnt].io_index = phys_offset;
 +    mmio[mmio_cnt].start = start_addr;
 +    mmio[mmio_cnt++].size = size;
 +}
 +
 +/* mem_read and mem_write are arrays of functions containing the
 +   function to access byte (index 0), word (index 1) and dword (index
 +   2). All functions must be supplied. If io_index is non zero, the
 +   corresponding io zone is modified. If it is zero, a new io zone is
 +   allocated. The return value can be used with
 +   cpu_register_physical_memory(). (-1) is returned if error. */
 +int cpu_register_io_memory(int io_index,
 +                           CPUReadMemoryFunc **mem_read,
 +                           CPUWriteMemoryFunc **mem_write,
 +                           void *opaque)
 +{
 +    int i;
 +
 +    if (io_index <= 0) {
 +        if (io_index >= IO_MEM_NB_ENTRIES)
 +            return -1;
 +        io_index = io_mem_nb++;
 +    } else {
 +        if (io_index >= IO_MEM_NB_ENTRIES)
 +            return -1;
 +    }
 +    
 +    for(i = 0;i < 3; i++) {
 +        io_mem_read[io_index][i] = mem_read[i];
 +        io_mem_write[io_index][i] = mem_write[i];
 +    }
 +    io_mem_opaque[io_index] = opaque;
 +    return io_index << IO_MEM_SHIFT;
 +}
 +
 +CPUWriteMemoryFunc **cpu_get_io_memory_write(int io_index)
 +{
 +    return io_mem_write[io_index >> IO_MEM_SHIFT];
 +}
 +
 +CPUReadMemoryFunc **cpu_get_io_memory_read(int io_index)
 +{
 +    return io_mem_read[io_index >> IO_MEM_SHIFT];
 +}
 +
 +#ifdef __ia64__
 +
 +#define __ia64_fc(addr)       asm volatile ("fc %0" :: "r"(addr) : "memory")
 +#define ia64_sync_i() asm volatile (";; sync.i" ::: "memory")
 +#define ia64_srlz_i() asm volatile (";; srlz.i ;;" ::: "memory")
 +
 +/* IA64 has seperate I/D cache, with coherence maintained by DMA controller.
 + * So to emulate right behavior that guest OS is assumed, we need to flush
 + * I/D cache here.
 + */
 +static void sync_icache(uint8_t *address, int len)
 +{
 +    unsigned long addr = (unsigned long)address;
 +    unsigned long end = addr + len;
 +
 +    for (addr &= ~(32UL-1); addr < end; addr += 32UL)
 +        __ia64_fc(addr);
 +
 +    ia64_sync_i();
 +    ia64_srlz_i();
 +}
 +#endif 
 +
 +/* physical memory access (slow version, mainly for debug) */
 +#if defined(CONFIG_USER_ONLY)
 +void cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf, 
 +                            int len, int is_write)
 +{
 +    int l, flags;
 +    target_ulong page;
 +
 +    while (len > 0) {
 +        page = addr & TARGET_PAGE_MASK;
 +        l = (page + TARGET_PAGE_SIZE) - addr;
 +        if (l > len)
 +            l = len;
 +        flags = page_get_flags(page);
 +        if (!(flags & PAGE_VALID))
 +            return;
 +        if (is_write) {
 +            if (!(flags & PAGE_WRITE))
 +                return;
 +            memcpy((uint8_t *)addr, buf, len);
 +        } else {
 +            if (!(flags & PAGE_READ))
 +                return;
 +            memcpy(buf, (uint8_t *)addr, len);
 +        }
 +        len -= l;
 +        buf += l;
 +        addr += l;
 +    }
 +}
 +#else
 +
 +int iomem_index(target_phys_addr_t addr)
 +{
 +        int i;
 +
 +        for (i = 0; i < mmio_cnt; i++) {
 +                unsigned long start, end;
 +
 +                start = mmio[i].start;
 +                end = mmio[i].start + mmio[i].size;
 +
 +                if ((addr >= start) && (addr < end)){
 +                        return (mmio[i].io_index >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
 +                }
 +        }
 +        return 0;
 +}
 +
 +#if defined(__i386__) || defined(__x86_64__)
 +#define phys_ram_addr(x) (qemu_map_cache(x))
 +#elif defined(__ia64__)
 +#define phys_ram_addr(x) (((x) < ram_size) ? (phys_ram_base + (x)) : NULL)
 +#endif
 +
 +unsigned long *logdirty_bitmap;
 +unsigned long logdirty_bitmap_size;
 +
 +/*
 + * Replace the standard byte memcpy with a word memcpy for appropriately sized
 + * memory copy operations.  Some users (USB-UHCI) can not tolerate the possible
 + * word tearing that can result from a guest concurrently writing a memory
 + * structure while the qemu device model is modifying the same location.
 + * Forcing a word-sized read/write prevents the guest from seeing a partially
 + * written word-sized atom.
 + */
 +#if defined(__x86_64__) || defined(__i386__)
 +static void memcpy_words(void *dst, void *src, size_t n)
 +{
 +    asm volatile (
 +        "   movl %%edx,%%ecx \n"
 +#ifdef __x86_64__
 +        "   shrl $3,%%ecx    \n"
 +        "   rep  movsq       \n"
 +        "   test $4,%%edx    \n"
 +        "   jz   1f          \n"
 +        "   movsl            \n"
 +#else /* __i386__ */
 +        "   shrl $2,%%ecx    \n"
 +        "   rep  movsl       \n"
 +#endif
 +        "1: test $2,%%edx    \n"
 +        "   jz   1f          \n"
 +        "   movsw            \n"
 +        "1: test $1,%%edx    \n"
 +        "   jz   1f          \n"
 +        "   movsb            \n"
 +        "1:                  \n"
 +        : "+S" (src), "+D" (dst) : "d" (n) : "ecx", "memory" );
 +}
 +#else
 +static void memcpy_words(void *dst, void *src, size_t n)
 +{
 +    /* Some architectures do not like unaligned accesses. */
 +    if (((unsigned long)dst | (unsigned long)src) & 3) {
 +        memcpy(dst, src, n);
 +        return;
 +    }
 +
 +    while (n >= sizeof(uint32_t)) {
 +        *((uint32_t *)dst) = *((uint32_t *)src);
 +        dst = ((uint32_t *)dst) + 1;
 +        src = ((uint32_t *)src) + 1;
 +        n -= sizeof(uint32_t);
 +    }
 +
 +    if (n & 2) {
 +        *((uint16_t *)dst) = *((uint16_t *)src);
 +        dst = ((uint16_t *)dst) + 1;
 +        src = ((uint16_t *)src) + 1;
 +    }
 +
 +    if (n & 1) {
 +        *((uint8_t *)dst) = *((uint8_t *)src);
 +        dst = ((uint8_t *)dst) + 1;
 +        src = ((uint8_t *)src) + 1;
 +    }
 +}
 +#endif
 +
 +void cpu_physical_memory_rw(target_phys_addr_t _addr, uint8_t *buf, 
 +                            int _len, int is_write)
 +{
 +    target_phys_addr_t addr = _addr;
 +    int len = _len;
 +    int l, io_index;
 +    uint8_t *ptr;
 +    uint32_t val;
 +
 +    mapcache_lock();
 +
 +    while (len > 0) {
 +        /* How much can we copy before the next page boundary? */
 +        l = TARGET_PAGE_SIZE - (addr & ~TARGET_PAGE_MASK); 
 +        if (l > len)
 +            l = len;
 +
 +        io_index = iomem_index(addr);
 +        if (is_write) {
 +            if (io_index) {
 +                if (l >= 4 && ((addr & 3) == 0)) {
 +                    /* 32 bit read access */
 +                    val = ldl_raw(buf);
 +                    io_mem_write[io_index][2](io_mem_opaque[io_index], addr, val);
 +                    l = 4;
 +                } else if (l >= 2 && ((addr & 1) == 0)) {
 +                    /* 16 bit read access */
 +                    val = lduw_raw(buf);
 +                    io_mem_write[io_index][1](io_mem_opaque[io_index], addr, val);
 +                    l = 2;
 +                } else {
 +                    /* 8 bit access */
 +                    val = ldub_raw(buf);
 +                    io_mem_write[io_index][0](io_mem_opaque[io_index], addr, val);
 +                    l = 1;
 +                }
 +            } else if ((ptr = phys_ram_addr(addr)) != NULL) {
 +                /* Writing to RAM */
 +                memcpy_words(ptr, buf, l);
 +#ifndef CONFIG_STUBDOM
 +                if (logdirty_bitmap != NULL) {
 +                    /* Record that we have dirtied this frame */
 +                    unsigned long pfn = addr >> TARGET_PAGE_BITS;
 +                    if (pfn / 8 >= logdirty_bitmap_size) {
 +                        fprintf(logfile, "dirtying pfn %lx >= bitmap "
 +                                "size %lx\n", pfn, logdirty_bitmap_size * 8);
 +                    } else {
 +                        logdirty_bitmap[pfn / HOST_LONG_BITS]
 +                            |= 1UL << pfn % HOST_LONG_BITS;
 +                    }
 +                }
 +#endif
 +#ifdef __ia64__
 +                sync_icache(ptr, l);
 +#endif 
 +            }
 +        } else {
 +            if (io_index) {
 +                if (l >= 4 && ((addr & 3) == 0)) {
 +                    /* 32 bit read access */
 +                    val = io_mem_read[io_index][2](io_mem_opaque[io_index], addr);
 +                    stl_raw(buf, val);
 +                    l = 4;
 +                } else if (l >= 2 && ((addr & 1) == 0)) {
 +                    /* 16 bit read access */
 +                    val = io_mem_read[io_index][1](io_mem_opaque[io_index], addr);
 +                    stw_raw(buf, val);
 +                    l = 2;
 +                } else {
 +                    /* 8 bit access */
 +                    val = io_mem_read[io_index][0](io_mem_opaque[io_index], addr);
 +                    stb_raw(buf, val);
 +                    l = 1;
 +                }
 +            } else if ((ptr = phys_ram_addr(addr)) != NULL) {
 +                /* Reading from RAM */
 +                memcpy_words(buf, ptr, l);
 +            } else {
 +                /* Neither RAM nor known MMIO space */
 +                memset(buf, 0xff, len); 
 +            }
 +        }
 +        len -= l;
 +        buf += l;
 +        addr += l;
 +    }
 +
 +#ifdef CONFIG_STUBDOM
 +    if (logdirty_bitmap != NULL)
 +        xc_hvm_modified_memory(xc_handle, domid, _addr >> TARGET_PAGE_BITS,
 +                ((_addr + _len + TARGET_PAGE_SIZE - 1) >> TARGET_PAGE_BITS)
 +                    - (_addr >> TARGET_PAGE_BITS));
 +#endif
 +
 +    mapcache_unlock();
 +}
 +#endif
 +
 +/* virtual memory access for debug */
 +int cpu_memory_rw_debug(CPUState *env, target_ulong addr, 
 +                        uint8_t *buf, int len, int is_write)
 +{
 +    int l;
 +    target_ulong page, phys_addr;
 +
 +    while (len > 0) {
 +        page = addr & TARGET_PAGE_MASK;
 +        phys_addr = cpu_get_phys_page_debug(env, page);
 +        /* if no physical page mapped, return an error */
 +        if (phys_addr == -1)
 +            return -1;
 +        l = (page + TARGET_PAGE_SIZE) - addr;
 +        if (l > len)
 +            l = len;
 +        cpu_physical_memory_rw(phys_addr + (addr & ~TARGET_PAGE_MASK), 
 +                               buf, l, is_write);
 +        len -= l;
 +        buf += l;
 +        addr += l;
 +    }
 +    return 0;
 +}
 +
 +void cpu_physical_memory_reset_dirty(ram_addr_t start, ram_addr_t end,
 +                                     int dirty_flags)
 +{
 +      unsigned long length;
 +      int i, mask, len;
 +      uint8_t *p;
 +
 +      start &= TARGET_PAGE_MASK;
 +      end = TARGET_PAGE_ALIGN(end);
 +
 +      length = end - start;
 +      if (length == 0)
 +              return;
 +      mask = ~dirty_flags;
 +      p = phys_ram_dirty + (start >> TARGET_PAGE_BITS);
 +      len = length >> TARGET_PAGE_BITS;
 +      for(i = 0; i < len; i++)
 +              p[i] &= mask;
 +
 +      return;
 +}
 +
 +
 +/* Unoptimised in Xen DM, nicked from git
 + *  aab33094073678d459ccaac5c60ea7533e8d1d8e */
 +uint32_t ldub_phys(target_phys_addr_t addr)
 +{
 +    uint8_t val;
 +    cpu_physical_memory_read(addr, &val, 1);
 +    return val;
 +}
 +uint32_t lduw_phys(target_phys_addr_t addr)
 +{
 +    uint16_t val;
 +    cpu_physical_memory_read(addr, (uint8_t *)&val, 2);
 +    return tswap16(val);
 +}
 +uint64_t ldq_phys(target_phys_addr_t addr)
 +{
 +    uint64_t val;
 +    cpu_physical_memory_read(addr, (uint8_t *)&val, 8);
 +    return tswap64(val);
 +}
 +void stb_phys(target_phys_addr_t addr, uint32_t val)
 +{
 +    uint8_t v = val;
 +    cpu_physical_memory_write(addr, &v, 1);
 +}
 +void stw_phys(target_phys_addr_t addr, uint32_t val)
 +{
 +    uint16_t v = tswap16(val);
 +    cpu_physical_memory_write(addr, (const uint8_t *)&v, 2);
 +}
 +void stq_phys(target_phys_addr_t addr, uint64_t val)
 +{
 +    val = tswap64(val);
 +    cpu_physical_memory_write(addr, (const uint8_t *)&val, 8);
 +}
 +
 +/* stubs which we hope (think!) are OK for Xen DM */
 +void stl_phys(target_phys_addr_t addr, uint32_t val)
 +{
 +    val = tswap32(val);
 +    cpu_physical_memory_write(addr, (const uint8_t *)&val, 4);
 +}
 +void stl_phys_notdirty(target_phys_addr_t addr, uint32_t val)
 +{
 +    stl_phys(addr, val);
 +}
 +uint32_t ldl_phys(target_phys_addr_t addr)
 +{
 +    uint32_t val;
 +    cpu_physical_memory_read(addr, (uint8_t *)&val, 4);
 +    return tswap32(val);
 +}
 +
 +void cpu_physical_memory_write_rom(target_phys_addr_t addr, 
 +                                   const uint8_t *buf, int len) {
 +    return cpu_physical_memory_write(addr,buf,len);
 +}
 +
 +/* stub out various functions for Xen DM */
 +void dump_exec_info(FILE *f,
 +                    int (*cpu_fprintf)(FILE *f, const char *fmt, ...)) {
 +}
 +void monitor_disas(CPUState *env,
 +                   target_ulong pc, int nb_insn, int is_physical, int flags) {
 +}
 +void irq_info(void) { }
 +void pic_info(void) { }
index 2018829c185e1ca7441204b00ee897e4cd3e6fb9,0000000000000000000000000000000000000000..2cfb40dec1b6ccc8873f052c5bc8573a7ac3da18
mode 100644,000000..100644
--- /dev/null
@@@ -1,6 -1,0 +1,6 @@@
- BAD_LIBOBJS += translate-all.o
 +
 +BAD_LIBOBJS += exec.o cpu-exec.o tcg%.o translate.o host-utils.o
++BAD_LIBOBJS += translate-all.o op_helper.o
 +BAD_LIBOBJS += fpu/%.o helper.o disas.o
 +
 +LIBOBJS := $(filter-out $(BAD_LIBOBJS), $(LIBOBJS))
diff --cc keymaps.c
Simple merge
diff --cc monitor.c
index b15a1fa8484e1c5ae64848322572dbd568d808e4,3dcf1d0ffad9e1652da9673058db37472c59f9b1..fa06a606b6eaeaf3474e6c134cc425e209f1ab6a
+++ b/monitor.c
  //#define DEBUG
  //#define DEBUG_COMPLETION
  
- #ifndef offsetof
- #define offsetof(type, field) ((size_t) &((type *)0)->field)
- #endif
++#undef TARGET_I386
 +
  /*
   * Supported types:
   *
diff --cc osdep.c
Simple merge
diff --cc qemu-char.h
Simple merge
diff --cc qemu-common.h
Simple merge
diff --cc qemu-lock.h
index 0000000000000000000000000000000000000000,fdd8da94352e023bda241f4e49a71c1fdf0ebe00..584b225ec5991581b9b26f48aefa80750dc4a4b9
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,249 +1,253 @@@
+ /*
+  *  Copyright (c) 2003 Fabrice Bellard
+  *
+  * This library is free software; you can redistribute it and/or
+  * modify it under the terms of the GNU Lesser General Public
+  * License as published by the Free Software Foundation; either
+  * version 2 of the License, or (at your option) any later version.
+  *
+  * This library is distributed in the hope that it will be useful,
+  * but WITHOUT ANY WARRANTY; without even the implied warranty of
+  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  * Lesser General Public License for more details.
+  *
+  * You should have received a copy of the GNU Lesser General Public
+  * License along with this library; if not, write to the Free Software
+  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+  */
+ /* Locking primitives.  Most of this code should be redundant -
+    system emulation doesn't need/use locking, NPTL userspace uses
+    pthread mutexes, and non-NPTL userspace isn't threadsafe anyway.
+    In either case a spinlock is probably the wrong kind of lock.
+    Spinlocks are only good if you know annother CPU has the lock and is
+    likely to release it soon.  In environments where you have more threads
+    than physical CPUs (the extreme case being a single CPU host) a spinlock
+    simply wastes CPU until the OS decides to preempt it.  */
+ #if defined(USE_NPTL)
+ #include <pthread.h>
+ #define spin_lock pthread_mutex_lock
+ #define spin_unlock pthread_mutex_unlock
+ #define spinlock_t pthread_mutex_t
+ #define SPIN_LOCK_UNLOCKED PTHREAD_MUTEX_INITIALIZER
++#elif defined(CONFIG_STUBDOM)
++
++#include <spinlock.h>
++
+ #else
+ #if defined(__hppa__)
+ typedef int spinlock_t[4];
+ #define SPIN_LOCK_UNLOCKED { 1, 1, 1, 1 }
+ static inline void resetlock (spinlock_t *p)
+ {
+     (*p)[0] = (*p)[1] = (*p)[2] = (*p)[3] = 1;
+ }
+ #else
+ typedef int spinlock_t;
+ #define SPIN_LOCK_UNLOCKED 0
+ static inline void resetlock (spinlock_t *p)
+ {
+     *p = SPIN_LOCK_UNLOCKED;
+ }
+ #endif
+ #if defined(__powerpc__)
+ static inline int testandset (int *p)
+ {
+     int ret;
+     __asm__ __volatile__ (
+                           "0:    lwarx %0,0,%1\n"
+                           "      xor. %0,%3,%0\n"
+                           "      bne 1f\n"
+                           "      stwcx. %2,0,%1\n"
+                           "      bne- 0b\n"
+                           "1:    "
+                           : "=&r" (ret)
+                           : "r" (p), "r" (1), "r" (0)
+                           : "cr0", "memory");
+     return ret;
+ }
+ #elif defined(__i386__)
+ static inline int testandset (int *p)
+ {
+     long int readval = 0;
+     __asm__ __volatile__ ("lock; cmpxchgl %2, %0"
+                           : "+m" (*p), "+a" (readval)
+                           : "r" (1)
+                           : "cc");
+     return readval;
+ }
+ #elif defined(__x86_64__)
+ static inline int testandset (int *p)
+ {
+     long int readval = 0;
+     __asm__ __volatile__ ("lock; cmpxchgl %2, %0"
+                           : "+m" (*p), "+a" (readval)
+                           : "r" (1)
+                           : "cc");
+     return readval;
+ }
+ #elif defined(__s390__)
+ static inline int testandset (int *p)
+ {
+     int ret;
+     __asm__ __volatile__ ("0: cs    %0,%1,0(%2)\n"
+                         "   jl    0b"
+                         : "=&d" (ret)
+                         : "r" (1), "a" (p), "0" (*p)
+                         : "cc", "memory" );
+     return ret;
+ }
+ #elif defined(__alpha__)
+ static inline int testandset (int *p)
+ {
+     int ret;
+     unsigned long one;
+     __asm__ __volatile__ ("0: mov 1,%2\n"
+                         "     ldl_l %0,%1\n"
+                         "     stl_c %2,%1\n"
+                         "     beq %2,1f\n"
+                         ".subsection 2\n"
+                         "1:   br 0b\n"
+                         ".previous"
+                         : "=r" (ret), "=m" (*p), "=r" (one)
+                         : "m" (*p));
+     return ret;
+ }
+ #elif defined(__sparc__)
+ static inline int testandset (int *p)
+ {
+       int ret;
+       __asm__ __volatile__("ldstub    [%1], %0"
+                            : "=r" (ret)
+                            : "r" (p)
+                            : "memory");
+       return (ret ? 1 : 0);
+ }
+ #elif defined(__arm__)
+ static inline int testandset (int *spinlock)
+ {
+     register unsigned int ret;
+     __asm__ __volatile__("swp %0, %1, [%2]"
+                          : "=r"(ret)
+                          : "0"(1), "r"(spinlock));
+     return ret;
+ }
+ #elif defined(__mc68000)
+ static inline int testandset (int *p)
+ {
+     char ret;
+     __asm__ __volatile__("tas %1; sne %0"
+                          : "=r" (ret)
+                          : "m" (p)
+                          : "cc","memory");
+     return ret;
+ }
+ #elif defined(__hppa__)
+ /* Because malloc only guarantees 8-byte alignment for malloc'd data,
+    and GCC only guarantees 8-byte alignment for stack locals, we can't
+    be assured of 16-byte alignment for atomic lock data even if we
+    specify "__attribute ((aligned(16)))" in the type declaration.  So,
+    we use a struct containing an array of four ints for the atomic lock
+    type and dynamically select the 16-byte aligned int from the array
+    for the semaphore.  */
+ #define __PA_LDCW_ALIGNMENT 16
+ static inline void *ldcw_align (void *p) {
+     unsigned long a = (unsigned long)p;
+     a = (a + __PA_LDCW_ALIGNMENT - 1) & ~(__PA_LDCW_ALIGNMENT - 1);
+     return (void *)a;
+ }
+ static inline int testandset (spinlock_t *p)
+ {
+     unsigned int ret;
+     p = ldcw_align(p);
+     __asm__ __volatile__("ldcw 0(%1),%0"
+                          : "=r" (ret)
+                          : "r" (p)
+                          : "memory" );
+     return !ret;
+ }
+ #elif defined(__ia64)
+ #include <ia64intrin.h>
+ static inline int testandset (int *p)
+ {
+     return __sync_lock_test_and_set (p, 1);
+ }
+ #elif defined(__mips__)
+ static inline int testandset (int *p)
+ {
+     int ret;
+     __asm__ __volatile__ (
+       "       .set push               \n"
+       "       .set noat               \n"
+       "       .set mips2              \n"
+       "1:     li      $1, 1           \n"
+       "       ll      %0, %1          \n"
+       "       sc      $1, %1          \n"
+       "       beqz    $1, 1b          \n"
+       "       .set pop                "
+       : "=r" (ret), "+R" (*p)
+       :
+       : "memory");
+     return ret;
+ }
+ #else
+ #error unimplemented CPU support
+ #endif
+ #if defined(CONFIG_USER_ONLY)
+ static inline void spin_lock(spinlock_t *lock)
+ {
+     while (testandset(lock));
+ }
+ static inline void spin_unlock(spinlock_t *lock)
+ {
+     resetlock(lock);
+ }
+ static inline int spin_trylock(spinlock_t *lock)
+ {
+     return !testandset(lock);
+ }
+ #else
+ static inline void spin_lock(spinlock_t *lock)
+ {
+ }
+ static inline void spin_unlock(spinlock_t *lock)
+ {
+ }
+ static inline int spin_trylock(spinlock_t *lock)
+ {
+     return 1;
+ }
+ #endif
+ #endif
diff --cc sysemu.h
Simple merge
diff --cc tests/Makefile
index e73dbf1ba0e699acd22ef02b96424d02d65aa7a7,326b7335a3f32bf8cc5c4e6ef2945e1c3c547697..984af05561b408dd3be8ab923eb6cad8b94e4f4e
@@@ -1,5 -1,5 +1,6 @@@
 +QEMU_ROOT ?= ..
  -include ../config-host.mak
+ VPATH=$(SRC_PATH)/tests
  
  CFLAGS=-Wall -O2 -g -fno-strict-aliasing
  #CFLAGS+=-msse2
diff --cc vl.c
index 182346af469228e9e67b6adf0f422a8f34b6e33d,bb1cc8d21ee9e371b529b239926af0984e1ac51f..c2e5ab410554af885912e846d776408b15105f30
--- 1/vl.c
--- 2/vl.c
+++ b/vl.c
@@@ -28,8 -28,8 +28,9 @@@
  #include "hw/pc.h"
  #include "hw/audiodev.h"
  #include "hw/isa.h"
 +#include "hw/pci.h"
  #include "hw/baum.h"
+ #include "hw/bt.h"
  #include "net.h"
  #include "console.h"
  #include "sysemu.h"
  #include <mmsystem.h>
  #define getopt_long_only getopt_long
  #define memalign(align, size) malloc(size)
 +#define NO_UNIX_SOCKETS 1
  #endif
  
- #include "qemu_socket.h"
  #ifdef CONFIG_SDL
  #ifdef __APPLE__
  #include <SDL/SDL.h>
  /* XXX: use a two level table to limit memory usage */
  #define MAX_IOPORTS 65536
  
 +/* Max number of PCI emulation */
 +#define MAX_PCI_EMULATION 32
 +
  const char *bios_dir = CONFIG_QEMU_SHAREDIR;
  const char *bios_name = NULL;
- void *ioport_opaque[MAX_IOPORTS];
- IOPortReadFunc *ioport_read_table[3][MAX_IOPORTS];
- IOPortWriteFunc *ioport_write_table[3][MAX_IOPORTS];
static void *ioport_opaque[MAX_IOPORTS];
static IOPortReadFunc *ioport_read_table[3][MAX_IOPORTS];
static IOPortWriteFunc *ioport_write_table[3][MAX_IOPORTS];
  /* Note: drives_table[MAX_DRIVES] is a dummy block driver if none available
     to store the VM snapshots */
  DriveInfo drives_table[MAX_DRIVES+1];
@@@ -199,18 -201,9 +210,18 @@@ int graphic_width = 800
  int graphic_height = 600;
  int graphic_depth = 15;
  #endif
- int full_screen = 0;
- int no_frame = 0;
static int full_screen = 0;
static int no_frame = 0;
  int no_quit = 0;
 +#ifdef CONFIG_OPENGL
 +int opengl_enabled = 1;
 +#else
 +int opengl_enabled = 0;
 +#endif
 +static const char *direct_pci;
 +static int nb_pci_emulation = 0;
 +static char pci_emulation_config_text[MAX_PCI_EMULATION][256];
 +PCI_EMULATION_INFO *PciEmulationInfoHead = NULL;
  CharDriverState *serial_hds[MAX_SERIAL_PORTS];
  CharDriverState *parallel_hds[MAX_PARALLEL_PORTS];
  #ifdef TARGET_I386
@@@ -220,14 -213,6 +231,7 @@@ int usb_enabled = 0
  static VLANState *first_vlan;
  int smp_cpus = 1;
  const char *vnc_display;
- #if defined(TARGET_SPARC)
- #define MAX_CPUS 16
- #elif defined(TARGET_I386)
- #define MAX_CPUS 255
- #else
- #define MAX_CPUS 1
- #endif
 +int vncunused;
  int acpi_enabled = 1;
  int fd_bootchk = 1;
  int no_reboot = 0;
@@@ -913,9 -921,74 +942,74 @@@ static void rtc_stop_timer(struct qemu_
  
  #endif /* _WIN32 */
  
+ /* Correlation between real and virtual time is always going to be
+    fairly approximate, so ignore small variation.
+    When the guest is idle real and virtual time will be aligned in
+    the IO wait loop.  */
+ #define ICOUNT_WOBBLE (QEMU_TIMER_BASE / 10)
+ static void icount_adjust(void)
+ {
+     int64_t cur_time;
+     int64_t cur_icount;
+     int64_t delta;
+     static int64_t last_delta;
+     /* If the VM is not running, then do nothing.  */
+     if (!vm_running)
+         return;
+     cur_time = cpu_get_clock();
+     cur_icount = qemu_get_clock(vm_clock);
+     delta = cur_icount - cur_time;
+     /* FIXME: This is a very crude algorithm, somewhat prone to oscillation.  */
+     if (delta > 0
+         && last_delta + ICOUNT_WOBBLE < delta * 2
+         && icount_time_shift > 0) {
+         /* The guest is getting too far ahead.  Slow time down.  */
+         icount_time_shift--;
+     }
+     if (delta < 0
+         && last_delta - ICOUNT_WOBBLE > delta * 2
+         && icount_time_shift < MAX_ICOUNT_SHIFT) {
+         /* The guest is getting too far behind.  Speed time up.  */
+         icount_time_shift++;
+     }
+     last_delta = delta;
+     qemu_icount_bias = cur_icount - (qemu_icount << icount_time_shift);
+ }
+ static void icount_adjust_rt(void * opaque)
+ {
+     qemu_mod_timer(icount_rt_timer,
+                    qemu_get_clock(rt_clock) + 1000);
+     icount_adjust();
+ }
+ static void icount_adjust_vm(void * opaque)
+ {
+     qemu_mod_timer(icount_vm_timer,
+                    qemu_get_clock(vm_clock) + QEMU_TIMER_BASE / 10);
+     icount_adjust();
+ }
+ static void init_icount_adjust(void)
+ {
+     /* Have both realtime and virtual time triggers for speed adjustment.
+        The realtime trigger catches emulated time passing too slowly,
+        the virtual time trigger catches emulated time passing too fast.
+        Realtime triggers occur even when idle, so use them less frequently
+        than VM triggers.  */
+     icount_rt_timer = qemu_new_timer(rt_clock, icount_adjust_rt, NULL);
+     qemu_mod_timer(icount_rt_timer,
+                    qemu_get_clock(rt_clock) + 1000);
+     icount_vm_timer = qemu_new_timer(vm_clock, icount_adjust_vm, NULL);
+     qemu_mod_timer(icount_vm_timer,
+                    qemu_get_clock(vm_clock) + QEMU_TIMER_BASE / 10);
+ }
  static struct qemu_alarm_timer alarm_timers[] = {
  #ifndef _WIN32
 -#ifdef __linux__
 +#if defined(__linux__) && !defined(CONFIG_DM)
      {"dynticks", ALARM_FLAG_DYNTICKS, dynticks_start_timer,
       dynticks_stop_timer, dynticks_rearm_timer, NULL},
      /* HPET - if available - is preferred */
@@@ -2360,33 -2437,170 +2472,180 @@@ void cfmakeraw (struct termios *termios
  }
  #endif
  
- #if defined(__linux__) || defined(__sun__) || defined(__NetBSD__) || defined(__OpenBSD__)
- static int pty_getname(struct CharDriverState *chr, char *buf, size_t len) {
+ #if defined(__linux__) || defined(__sun__) || defined(__FreeBSD__) \
+     || defined(__NetBSD__) || defined(__OpenBSD__)
+ typedef struct {
+     int fd;
+     int connected;
+     int polling;
+     int read_bytes;
+     QEMUTimer *timer;
+ } PtyCharDriver;
+ static void pty_chr_update_read_handler(CharDriverState *chr);
+ static void pty_chr_state(CharDriverState *chr, int connected);
+ static int pty_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
+ {
+     PtyCharDriver *s = chr->opaque;
+     if (!s->connected) {
+         /* guest sends data, check for (re-)connect */
+         pty_chr_update_read_handler(chr);
+         return 0;
+     }
+     return qemu_write(s->fd, buf, len);
+ }
+ static int pty_chr_read_poll(void *opaque)
+ {
+     CharDriverState *chr = opaque;
+     PtyCharDriver *s = chr->opaque;
+     s->read_bytes = qemu_chr_can_read(chr);
+     return s->read_bytes;
+ }
+ static void pty_chr_read(void *opaque)
+ {
+     CharDriverState *chr = opaque;
+     PtyCharDriver *s = chr->opaque;
+     int size, len;
+     uint8_t buf[1024];
+     len = sizeof(buf);
+     if (len > s->read_bytes)
+         len = s->read_bytes;
+     if (len == 0)
+         return;
+     size = read(s->fd, buf, len);
+     if ((size == -1 && errno == EIO) ||
+         (size == 0)) {
+         pty_chr_state(chr, 0);
+         return;
+     }
+     if (size > 0) {
+         pty_chr_state(chr, 1);
+         qemu_chr_read(chr, buf, size);
+     }
+ }
+ static void pty_chr_update_read_handler(CharDriverState *chr)
+ {
+     PtyCharDriver *s = chr->opaque;
+     qemu_set_fd_handler2(s->fd, pty_chr_read_poll,
+                          pty_chr_read, NULL, chr);
+     s->polling = 1;
+     /*
+      * Short timeout here: just need wait long enougth that qemu makes
+      * it through the poll loop once.  When reconnected we want a
+      * short timeout so we notice it almost instantly.  Otherwise
+      * read() gives us -EIO instantly, making pty_chr_state() reset the
+      * timeout to the normal (much longer) poll interval before the
+      * timer triggers.
+      */
+     qemu_mod_timer(s->timer, qemu_get_clock(rt_clock) + 10);
+ }
+ static void pty_chr_state(CharDriverState *chr, int connected)
+ {
+     PtyCharDriver *s = chr->opaque;
+     if (!connected) {
+         qemu_set_fd_handler2(s->fd, NULL, NULL, NULL, NULL);
+         s->connected = 0;
+         s->polling = 0;
+         /* (re-)connect poll interval for idle guests: once per second.
+          * We check more frequently in case the guests sends data to
+          * the virtual device linked to our pty. */
+         qemu_mod_timer(s->timer, qemu_get_clock(rt_clock) + 1000);
+     } else {
+         if (!s->connected)
+             qemu_chr_reset(chr);
+         s->connected = 1;
+     }
+ }
+ static void pty_chr_timer(void *opaque)
+ {
+     struct CharDriverState *chr = opaque;
+     PtyCharDriver *s = chr->opaque;
+     if (s->connected)
+         return;
+     if (s->polling) {
+         /* If we arrive here without polling being cleared due
+          * read returning -EIO, then we are (re-)connected */
+         pty_chr_state(chr, 1);
+         return;
+     }
+     /* Next poll ... */
+     pty_chr_update_read_handler(chr);
+ }
++static int pty_chr_getname(struct CharDriverState *chr, char *buf, size_t len) {
 +    char *name;
 +    FDCharDriver *s = chr->opaque;
 +
 +    name = ptsname(s->fd_in);
 +    if (!name) return -1;
 +    return snprintf(buf,len, "pty %s", name);
 +}
 +
+ static void pty_chr_close(struct CharDriverState *chr)
+ {
+     PtyCharDriver *s = chr->opaque;
+     qemu_set_fd_handler2(s->fd, NULL, NULL, NULL, NULL);
+     close(s->fd);
+     qemu_free(s);
+ }
  static CharDriverState *qemu_chr_open_pty(void)
  {
-     struct termios tty;
-     int master_fd, slave_fd;
      CharDriverState *chr;
+     PtyCharDriver *s;
+     struct termios tty;
+     int slave_fd;
+ #if defined(__OpenBSD__)
+     char pty_name[PATH_MAX];
+ #define q_ptsname(x) pty_name
+ #else
+     char *pty_name = NULL;
+ #define q_ptsname(x) ptsname(x)
+ #endif
+     chr = qemu_mallocz(sizeof(CharDriverState));
+     if (!chr)
+         return NULL;
+     s = qemu_mallocz(sizeof(PtyCharDriver));
+     if (!s) {
+         qemu_free(chr);
+         return NULL;
+     }
  
-     if (openpty(&master_fd, &slave_fd, NULL, NULL, NULL) < 0) {
+     if (openpty(&s->fd, &slave_fd, pty_name, NULL, NULL) < 0) {
          return NULL;
      }
  
      /* Set raw attributes on the pty. */
      cfmakeraw(&tty);
      tcsetattr(slave_fd, TCSAFLUSH, &tty);
+     close(slave_fd);
+     fprintf(stderr, "char device redirected to %s\n", q_ptsname(s->fd));
+     chr->opaque = s;
+     chr->chr_write = pty_chr_write;
+     chr->chr_update_read_handler = pty_chr_update_read_handler;
+     chr->chr_close = pty_chr_close;
++    chr->chr_getname = pty_chr_getname;
+     s->timer = qemu_new_timer(rt_clock, pty_chr_timer, chr);
  
-     fprintf(stderr, "char device redirected to %s\n", ptsname(master_fd));
-     chr = qemu_chr_open_fd(master_fd, master_fd);
-     chr->chr_getname = pty_getname;
      return chr;
  }
  
@@@ -3442,11 -3681,10 +3726,10 @@@ static CharDriverState *qemu_chr_open_t
  
      if (is_listen) {
          /* allow fast reuse */
 -#ifndef _WIN32
 +#ifndef NO_UNIX_SOCKETS
        if (is_unix) {
            char path[109];
-           strncpy(path, uaddr.sun_path, 108);
-           path[108] = 0;
+           pstrcpy(path, sizeof(path), uaddr.sun_path);
            unlink(path);
        } else
  #endif
@@@ -6495,11 -7188,6 +7297,11 @@@ void do_info_snapshots(void
  /***********************************************************/
  /* ram save/restore */
  
- static void ram_save(QEMUFile *f, void *opaque) { }
 +#ifdef CONFIG_DM
++static int ram_save_live(QEMUFile *f, int stage, void *opaque) { return 0; }
 +static int ram_load(QEMUFile *f, void *opaque, int version_id) { return 0; }
 +#else /* !CONFIG_DM */
 +
  static int ram_get_page(QEMUFile *f, uint8_t *buf, int len)
  {
      int v;
@@@ -6756,8 -7455,19 +7569,21 @@@ static int ram_load(QEMUFile *f, void *
      return 0;
  }
  
 +#endif /* !CONFIG_DM */
 +
+ void qemu_service_io(void)
+ {
+     CPUState *env = cpu_single_env;
+     if (env) {
+         cpu_interrupt(env, CPU_INTERRUPT_EXIT);
+ #ifdef USE_KQEMU
+         if (env->kqemu_enabled) {
+             kqemu_cpu_interrupt(env);
+         }
+ #endif
+     }
+ }
  /***********************************************************/
  /* bottom halves (can be seen as timers which expire ASAP) */
  
@@@ -7491,13 -8248,10 +8380,11 @@@ enum 
      QEMU_OPTION_bios,
      QEMU_OPTION_k,
      QEMU_OPTION_localtime,
-     QEMU_OPTION_cirrusvga,
-     QEMU_OPTION_vmsvga,
      QEMU_OPTION_g,
-     QEMU_OPTION_std_vga,
+     QEMU_OPTION_vga,
      QEMU_OPTION_echr,
      QEMU_OPTION_monitor,
 +    QEMU_OPTION_domainname,
      QEMU_OPTION_serial,
      QEMU_OPTION_parallel,
      QEMU_OPTION_loadvm,
@@@ -7602,10 -8351,9 +8492,10 @@@ static const QEMUOption qemu_options[] 
      { "g", 1, QEMU_OPTION_g },
  #endif
      { "localtime", 0, QEMU_OPTION_localtime },
-     { "std-vga", 0, QEMU_OPTION_std_vga },
+     { "vga", HAS_ARG, QEMU_OPTION_vga },
      { "echr", HAS_ARG, QEMU_OPTION_echr },
      { "monitor", HAS_ARG, QEMU_OPTION_monitor },
 +    { "domain-name", 1, QEMU_OPTION_domainname },
      { "serial", HAS_ARG, QEMU_OPTION_serial },
      { "parallel", HAS_ARG, QEMU_OPTION_parallel },
      { "loadvm", HAS_ARG, QEMU_OPTION_loadvm },
@@@ -7862,40 -8683,11 +8833,42 @@@ int main(int argc, char **argv
      const char *usb_devices[MAX_USB_CMDLINE];
      int usb_devices_index;
      int fds[2];
 +#ifndef CONFIG_STUBDOM
 +    struct rlimit rl;
 +#endif
+     int tb_size;
      const char *pid_file = NULL;
      VLANState *vlan;
+     int autostart;
  
 +    logfile = stderr; /* initial value */
 +
 +#if !defined(__sun__) && !defined(CONFIG_STUBDOM)
 +    /* Maximise rlimits. Needed where default constraints are tight (*BSD). */
 +    if (getrlimit(RLIMIT_STACK, &rl) != 0) {
 +       perror("getrlimit(RLIMIT_STACK)");
 +       exit(1);
 +    }
 +    rl.rlim_cur = rl.rlim_max;
 +    if (setrlimit(RLIMIT_STACK, &rl) != 0)
 +       perror("setrlimit(RLIMIT_STACK)");
 +    if (getrlimit(RLIMIT_DATA, &rl) != 0) {
 +       perror("getrlimit(RLIMIT_DATA)");
 +       exit(1);
 +    }
 +    rl.rlim_cur = rl.rlim_max;
 +    if (setrlimit(RLIMIT_DATA, &rl) != 0)
 +       perror("setrlimit(RLIMIT_DATA)");
 +    rl.rlim_cur = RLIM_INFINITY;
 +    rl.rlim_max = RLIM_INFINITY;
 +    if (setrlimit(RLIMIT_RSS, &rl) != 0)
 +       perror("setrlimit(RLIMIT_RSS)");
 +    rl.rlim_cur = RLIM_INFINITY;
 +    rl.rlim_max = RLIM_INFINITY;
 +    if (setrlimit(RLIMIT_MEMLOCK, &rl) != 0)
 +       perror("setrlimit(RLIMIT_MEMLOCK)");
 + #endif
 + 
      LIST_INIT (&vm_change_state_head);
  #ifndef _WIN32
      {
      linux_boot = (kernel_filename != NULL);
      net_boot = (boot_devices_bitmap >> ('n' - 'a')) & 0xF;
  
 +#ifndef CONFIG_DM
 +    /* XXX: this should not be: some embedded targets just have flash */
      if (!linux_boot && net_boot == 0 &&
-         nb_drives_opt == 0)
+         !machine->nodisk_ok && nb_drives_opt == 0)
          help(1);
 +#endif /*!CONFIG_DM*/
  
+     if (!linux_boot && *kernel_cmdline != '\0') {
+         fprintf(stderr, "-append only allowed with -kernel option\n");
+         exit(1);
+     }
+     if (!linux_boot && initrd_filename != NULL) {
+         fprintf(stderr, "-initrd only allowed with -kernel option\n");
+         exit(1);
+     }
      /* boot to floppy or the default cd if no hard disk defined yet */
      if (!boot_devices[0]) {
          boot_devices = "cad";
          fprintf(stderr, "Could not allocate physical memory\n");
          exit(1);
      }
 +#endif
  
+     /* init the dynamic translator */
+     cpu_exec_init_all(tb_size * 1024 * 1024);
      bdrv_init();
  
 +    xc_handle = xc_interface_open();
 +#ifdef CONFIG_STUBDOM
 +    {
 +        char *domid_s, *msg;
 +        if ((msg = xenbus_read(XBT_NIL, "domid", &domid_s)))
 +            fprintf(stderr,"Can not read our own domid: %s\n", msg);
 +        else
 +            xenstore_parse_domain_config(atoi(domid_s));
 +    }
 +#else
 +    xenstore_parse_domain_config(domid);
 +#endif /* CONFIG_STUBDOM */
 +
      /* we always create the cdrom drive, even if no disk is there */
  
 +#ifndef CONFIG_DM
      if (nb_drives_opt < MAX_DRIVES)
          drive_add(NULL, CDROM_ALIAS);
 +#endif
  
      /* we always create at least one floppy */
  
  
                  if (sscanf(vc->info_str, "tap: ifname=%63s ", ifname) == 1 &&
                      s->down_script[0])
 -                    launch_script(s->down_script, ifname, s->fd);
 +                    launch_script(s->down_script, ifname, s->script_arg, s->fd);
              }
+ #if defined(CONFIG_VDE)
+             if (vc->fd_read == vde_from_qemu) {
+                 VDEState *s = vc->opaque;
+                 vde_close(s->vde);
+             }
+ #endif
          }
      }
  #endif
diff --cc vnc.c
index 01e22e544ad2669131abc13c216c0a3efbc3b54f,ffba33f04c2db25525e40bf5e4e743a3773398cd..bb77739751d54cc18df7c02a20b5d43bf02dbd79
--- 1/vnc.c
--- 2/vnc.c
+++ b/vnc.c
  
  // #define _VNC_DEBUG 1
  
- #if _VNC_DEBUG
+ #ifdef _VNC_DEBUG
  #define VNC_DEBUG(fmt, ...) do { fprintf(stderr, fmt, ## __VA_ARGS__); } while (0)
  
--#if CONFIG_VNC_TLS && _VNC_DEBUG >= 2
++#if defined(CONFIG_VNC_TLS) && _VNC_DEBUG >= 2
  /* Very verbose, so only enabled for _VNC_DEBUG >= 2 */
  static void vnc_debug_gnutls_log(int level, const char* str) {
      VNC_DEBUG("%d %s", level, str);
@@@ -200,9 -152,8 +198,9 @@@ struct VncStat
      char *x509key;
  #endif
      char challenge[VNC_AUTH_CHALLENGE_SIZE];
 +    int switchbpp;
  
- #if CONFIG_VNC_TLS
+ #ifdef CONFIG_VNC_TLS
      int wiremode;
      gnutls_session_t tls_session;
  #endif
@@@ -322,37 -251,29 +320,42 @@@ static inline int vnc_and_bits(const ui
      }
      return 0;
  }
 +#endif
  
 -static void vnc_dpy_update(DisplayState *ds, int x, int y, int w, int h)
 +static void set_bits_in_row(VncState *vs, uint64_t *row,
 +                          int x, int y, int w, int h)
  {
 -    VncState *vs = ds->opaque;
 -    int i;
 +    int x1, x2;
 +    uint64_t mask;
 +
 +    if (w == 0)
 +      return;
 +
 +    x1 = X2DP_DOWN(vs, x);
 +    x2 = X2DP_UP(vs, x + w);
 +
 +    if (X2DP_UP(vs, w) != DIRTY_PIXEL_BITS)
 +      mask = ((1ULL << (x2 - x1)) - 1) << x1;
 +    else
 +      mask = ~(0ULL);
  
      h += y;
 +    if (h > vs->ds->height)
 +        h = vs->ds->height;
 +    for (; y < h; y++)
 +      row[y] |= mask;
 +}
  
 -    /* round x down to ensure the loop only spans one 16-pixel block per,
 -       iteration.  otherwise, if (x % 16) != 0, the last iteration may span
 -       two 16-pixel blocks but we only mark the first as dirty
 -    */
 -    w += (x % 16);
 -    x -= (x % 16);
 +static void vnc_dpy_update(DisplayState *ds, int x, int y, int w, int h)
 +{
 +    VncState *vs = ds->opaque;
  
 -    w = MIN(x + w, vs->width) - x;
+     x = MIN(x, vs->width);
+     y = MIN(y, vs->height);
 -    for (; y < h; y++)
 -      for (i = 0; i < w; i += 16)
 -          vnc_set_bit(vs->dirty_row[y], (x + i) / 16);
++    w = MIN(x, vs->width - x);
+     h = MIN(h, vs->height);
 +    set_bits_in_row(vs, vs->dirty_row, x, y, w, h);
  }
  
  static void vnc_framebuffer_update(VncState *vs, int x, int y, int w, int h,
      vnc_write_s32(vs, encoding);
  }
  
- static int mult_overflows(int x, int y)
- {
-     if (x<=0 || y<=0 || x>=INT_MAX/y)
-         return 1;
-     else return 0;
- }
 -static void vnc_dpy_resize(DisplayState *ds, int w, int h)
 +static void vnc_dpy_resize_shared(DisplayState *ds, int w, int h, int depth, int linesize, void *pixels)
  {
 +    static int allocated;
      int size_changed;
      VncState *vs = ds->opaque;
 +    int o;
  
 -    ds->data = qemu_realloc(ds->data, w * h * vs->depth);
 -    vs->old_data = qemu_realloc(vs->old_data, w * h * vs->depth);
 +    vnc_colourdepth(ds, depth);
-     if (mult_overflows(w, h) || mult_overflows(w*h, vs->depth) ||
-         mult_overflows(h, sizeof(vs->dirty_row[0]))) {
-         fprintf(stderr, "vnc: suspicious vnc_dpy_resize arguments"
-               " (w=%d h=%d depth=%d linesize=%d vs->depth=%d), exiting\n",
-               w, h, depth, linesize, vs->depth);
-         exit(1);
-     }
 +    if (!ds->shared_buf) {
 +        ds->linesize = w * vs->depth;
 +        if (allocated)
-             ds->data = realloc(ds->data,  h * ds->linesize);
++            ds->data = qemu_realloc(ds->data,  h * ds->linesize);
 +        else
 +            ds->data = malloc(h * ds->linesize);
 +        allocated = 1;
 +    } else {
 +        ds->linesize = linesize;
 +        if (allocated) {
 +            free(ds->data);
 +            allocated = 0;
 +        }
 +    }
-     vs->old_data = realloc(vs->old_data, h * ds->linesize);
-     vs->dirty_row = realloc(vs->dirty_row, h * sizeof(vs->dirty_row[0]));
-     vs->update_row = realloc(vs->update_row, h * sizeof(vs->dirty_row[0]));
++    vs->old_data = qemu_realloc(vs->old_data, h * ds->linesize);
++    vs->dirty_row = qemu_realloc(vs->dirty_row, h * sizeof(vs->dirty_row[0]));
++    vs->update_row = qemu_realloc(vs->update_row, h * sizeof(vs->dirty_row[0]));
  
 -    if (ds->data == NULL || vs->old_data == NULL) {
 +    if (ds->data == NULL || vs->old_data == NULL ||
 +      vs->dirty_row == NULL || vs->update_row == NULL) {
        fprintf(stderr, "vnc: memory allocation failed\n");
        exit(1);
      }
@@@ -1006,9 -704,8 +995,9 @@@ static int vnc_client_io_error(VncStat
        vs->ds->idle = 1;
        buffer_reset(&vs->input);
        buffer_reset(&vs->output);
 -      vs->need_update = 0;
 +        free_queue(vs);
 +        vs->update_requested = 0;
- #if CONFIG_VNC_TLS
+ #ifdef CONFIG_VNC_TLS
        if (vs->tls_session) {
            gnutls_deinit(vs->tls_session);
            vs->tls_session = NULL;
@@@ -1177,10 -872,10 +1166,10 @@@ static uint32_t read_u32(uint8_t *data
            (data[offset + 2] << 8) | data[offset + 3]);
  }
  
- #if CONFIG_VNC_TLS
+ #ifdef CONFIG_VNC_TLS
 -static ssize_t vnc_tls_push(gnutls_transport_ptr_t transport,
 -                            const void *data,
 -                            size_t len) {
 +ssize_t vnc_tls_push(gnutls_transport_ptr_t transport,
 +                   const void *data,
 +                   size_t len) {
      struct VncState *vs = (struct VncState *)transport;
      int ret;
  
@@@ -1975,7 -1610,7 +1964,7 @@@ static int vnc_tls_initialize(void
      if (gnutls_dh_params_generate2 (dh_params, DH_BITS) < 0)
        return 0;
  
- #if _VNC_DEBUG == 2
 -#if defined(_VNC_DEBUG) && _VNC_DEBUG >= 2
++#if defined(_VNC_DEBUG) && _VNC_DEBUG == 2
      gnutls_global_set_log_level(10);
      gnutls_global_set_log_function(vnc_debug_gnutls_log);
  #endif
@@@ -2533,17 -2175,13 +2522,17 @@@ void vnc_display_init(DisplayState *ds
      vs->ds->data = NULL;
      vs->ds->dpy_update = vnc_dpy_update;
      vs->ds->dpy_resize = vnc_dpy_resize;
 +    vs->ds->dpy_setdata = vnc_dpy_setdata;
 +    vs->ds->dpy_resize_shared = vnc_dpy_resize_shared;
      vs->ds->dpy_refresh = NULL;
  
 -    vnc_colordepth(vs->ds, 32);
 -    vnc_dpy_resize(vs->ds, 640, 400);
 +    vs->ds->width = 640;
 +    vs->ds->height = 400;
 +    vs->ds->linesize = 640 * 4;
 +    vnc_dpy_resize_shared(ds, ds->width, ds->height, 24, ds->linesize, NULL);
  }
  
- #if CONFIG_VNC_TLS
+ #ifdef CONFIG_VNC_TLS
  static int vnc_set_x509_credential(VncState *vs,
                                   const char *certdir,
                                   const char *filename,
@@@ -2619,9 -2257,8 +2608,9 @@@ void vnc_display_close(DisplayState *ds
        vs->csock = -1;
        buffer_reset(&vs->input);
        buffer_reset(&vs->output);
 -      vs->need_update = 0;
 +        free_queue(vs);
 +        vs->update_requested = 0;
- #if CONFIG_VNC_TLS
+ #ifdef CONFIG_VNC_TLS
        if (vs->tls_session) {
            gnutls_deinit(vs->tls_session);
            vs->tls_session = NULL;
@@@ -2671,7 -2302,8 +2660,7 @@@ int vnc_display_open(DisplayState *ds, 
      VncState *vs = ds ? (VncState *)ds->opaque : vnc_state;
      const char *options;
      int password = 0;
- #if CONFIG_VNC_TLS
 -    int reverse = 0;
+ #ifdef CONFIG_VNC_TLS
      int tls = 0, x509 = 0;
  #endif
  
        options++;
        if (strncmp(options, "password", 8) == 0) {
            password = 1; /* Require password auth */
 -      } else if (strncmp(options, "reverse", 7) == 0) {
 -          reverse = 1;
 +        } else if (strncmp(options, "switchbpp", 9) == 0) {
 +            vs->switchbpp = 1;
- #if CONFIG_VNC_TLS
+ #ifdef CONFIG_VNC_TLS
        } else if (strncmp(options, "tls", 3) == 0) {
            tls = 1; /* Require TLS */
        } else if (strncmp(options, "x509", 4) == 0) {
diff --cc vnc_keysym.h
Simple merge
index c6da4b3a05d94ed0580be072ab76f8a37233260f,0000000000000000000000000000000000000000..5e84c7b3b10c4f5093786057531fabfe80976837
mode 100644,000000..100644
--- /dev/null
@@@ -1,48 -1,0 +1,42 @@@
- #ifdef bool
- # define XEN_CONFIG_HOST_BOOL_WAS_DEFINED 1
- #else
- # define bool xen_bool
- #endif
 +#ifdef __MINIOS__
 +#define CONFIG_STUBDOM
 +#define NO_AIO 1
 +#define NO_UNIX_SOCKETS 1
 +#endif
 +
 +extern char domain_name[64];
 +extern int domid, domid_backend;
 +
 +#include <errno.h>
- #ifndef XEN_CONFIG_HOST_BOOL_WAS_DEFINED
- # undef bool
- #endif
++#include <stdbool.h>
 +
 +#include "xenctrl.h"
 +#include "xs.h"
 +#ifndef CONFIG_STUBDOM
 +#include "blktaplib.h"
 +#endif
 +
 +#define BIOS_SIZE ((256 + 64) * 1024)
 +
 +#undef CONFIG_GDBSTUB
 +
 +void main_loop_prepare(void);
 +
 +extern int xc_handle;
 +extern int xen_pause_requested;
 +extern int vcpus;
 +
 +#define DEFAULT_NETWORK_SCRIPT "/etc/xen/qemu-ifup"
 +#define DEFAULT_NETWORK_DOWN_SCRIPT "/etc/xen/qemu-ifdown"
 +
 +void xenstore_parse_domain_config(int domid);
 +void xenstore_read_vncpasswd(int domid, char *pwbuf, size_t pwbuflen);
 +#ifdef CONFIG_STUBDOM
 +extern struct BlockDriver bdrv_vbd;
 +#endif
 +struct CharDriverState;
 +void xenstore_store_serial_port_info(int i, struct CharDriverState *chr,
 +                                   const char *devname);
++
++extern unsigned long *logdirty_bitmap;
++extern unsigned long logdirty_bitmap_size;
index b02dcb0529597d7d1c643100b34506113ef48fe1,0000000000000000000000000000000000000000..b1912e595c80af5b38b605d5378ce8d4544e7f5a
mode 100644,000000..100644
--- /dev/null
@@@ -1,11 -1,0 +1,14 @@@
 +QEMU_ROOT ?= .
 +XEN_ROOT ?= $(QEMU_ROOT)/../xen-unstable.hg
 +include $(XEN_ROOT)/tools/Rules.mk
 +
 +ifdef CONFIG_STUBDOM
 +TARGET_DIRS=i386-stubdom
 +else
 +TARGET_DIRS=i386-dm
 +endif
 +
++SUBDIR_RULES=subdir-$(TARGET_DIRS)
++subdir-$(TARGET_DIRS): libqemu_common.a
++
 +-include $(QEMU_ROOT)/xen-hooks.mak
diff --cc xen-hooks.mak
index 230d03ac5767daa521cb88d87e39012e5b1da200,0000000000000000000000000000000000000000..95611f16340b80292f7910edeaf091a9a24da4e0
mode 100644,000000..100644
--- /dev/null
@@@ -1,77 -1,0 +1,78 @@@
 +CPPFLAGS+= -I$(XEN_ROOT)/tools/libxc
 +CPPFLAGS+= -I$(XEN_ROOT)/tools/xenstore
 +CPPFLAGS+= -I$(XEN_ROOT)/tools/include
 +
 +SSE2 := $(call cc-option,-msse2,)
 +ifeq ($(SSE2),-msse2)
 +CFLAGS += -DUSE_SSE2=1 -msse2
 +endif
 +
 +QEMU_PROG=qemu-dm
 +
 +CFLAGS += -Wno-unused -Wno-declaration-after-statement
 +
 +ifeq (,$(shell $(CC) -Wno-pointer-sign -E - </dev/null >/dev/null || echo x))
 +CFLAGS += -Wno-pointer-sign
 +endif 
 +
 +CFLAGS += $(CMDLINE_CFLAGS)
 +
 +LIBS += -L$(XEN_ROOT)/tools/libxc -lxenctrl -lxenguest
 +LIBS += -L$(XEN_ROOT)/tools/xenstore -lxenstore
 +
 +LDFLAGS := $(CFLAGS) $(LDFLAGS)
 +
 +OBJS += piix4acpi.o
 +OBJS += xenstore.o
 +OBJS += xen_platform.o
 +OBJS += xen_machine_fv.o
 +OBJS += xen_machine_pv.o
 +OBJS += xenfb.o
 +OBJS += xen_console.o
 +OBJS += xen_machine_fv.o
 +OBJS += exec-dm.o
 +OBJS += pci_emulation.o
++OBJS += helper2.o
 +
 +ifdef CONFIG_STUBDOM
 +CPPFLAGS += $(TARGET_CPPFLAGS)
 +CONFIG_SDL=
 +CONFIG_AUDIO=
 +OBJS += xenfbfront.o
 +else
 +CPPFLAGS+= -I$(XEN_ROOT)/tools/blktap/lib
 +LIBS += -L$(XEN_ROOT)/tools/blktap/lib -lblktap
 +OBJS += xen_blktap.o
 +OBJS += tpm_tis.o
 +endif
 +
 +ifdef CONFIG_STUBDOM
 +CONFIG_PASSTHROUGH=1
 +else
 +  ifeq (,$(wildcard /usr/include/pci))
 +$(warning *** pciutils-dev package not found - missing /usr/include/pci)
 +$(warning *** PCI passthrough capability has been disabled)
 +  else
 +CONFIG_PASSTHROUGH=1
 +  endif
 +endif
 +
 +ifdef CONFIG_PASSTHROUGH
 +OBJS+= pass-through.o pt-msi.o
 +LIBS += -lpci
 +CFLAGS += -DCONFIG_PASSTHROUGH 
 +$(info *** PCI passthrough capability has been enabled ***)
 +endif
 +
 +BAD_OBJS += gdbstub.o acpi.o apic.o
 +BAD_OBJS += vmmouse.o vmport.o tcg* helper.o
 +
 +OBJS := $(filter-out $(BAD_OBJS), $(OBJS))
 +
 +EXESUF=-xen
 +
 +datadir := $(subst qemu,xen/qemu,$(datadir))
 +docdir :=  $(subst qemu,xen/qemu,$(docdir))
 +mandir :=  $(subst share/man,share/xen/man,$(mandir))
 +
 +configdir := /etc/xen
diff --cc xen-vl-extra.c
index 8c3dc6b31271ad0be6df1e8297eefc3c86a23450,0000000000000000000000000000000000000000..d9e11fb70f2b5c05c347ad362091a138b20df072
mode 100644,000000..100644
--- /dev/null
@@@ -1,107 -1,0 +1,102 @@@
- /* forward declarations of things in vl.c */
- static int qemu_savevm_state(QEMUFile *f);
- static int qemu_loadvm_state(QEMUFile *f);
 +/*
 + * We #include this from vl.c.
 + *
 + * This is a bit yucky, but it means that the line numbers and other
 + * textual differences in vl.c remain small.
 + */
 +/* There is no need for multiple-inclusion protection since
 + * there is only one place where this file is included. */
 +
 +#include "qemu-xen.h"
 +
 +/* We use simpler state save/load functions for Xen */
 +
 +void do_savevm(const char *name)
 +{
 +    QEMUFile *f;
 +    int saved_vm_running, ret;
 +
 +    f = qemu_fopen(name, "wb");
 +    
 +    /* ??? Should this occur after vm_stop?  */
 +    qemu_aio_flush();
 +
 +    saved_vm_running = vm_running;
 +    vm_stop(0);
 +
 +    if (!f) {
 +        fprintf(logfile, "Failed to open savevm file '%s'\n", name);
 +        goto the_end;
 +    }
 +    
 +    ret = qemu_savevm_state(f);
 +    qemu_fclose(f);
 +
 +    if (ret < 0)
 +        fprintf(logfile, "Error %d while writing VM to savevm file '%s'\n",
 +                ret, name);
 +
 + the_end:
 +    if (saved_vm_running)
 +        vm_start();
 +
 +    return;
 +}
 +void do_loadvm(const char *name)
 +{
 +    QEMUFile *f;
 +    int saved_vm_running, ret;
 +
 +    /* Flush all IO requests so they don't interfere with the new state.  */
 +    qemu_aio_flush();
 +
 +    saved_vm_running = vm_running;
 +    vm_stop(0);
 +
 +    /* restore the VM state */
 +    f = qemu_fopen(name, "rb");
 +    if (!f) {
 +        fprintf(logfile, "Could not open VM state file\n");
 +        goto the_end;
 +    }
 +
 +    ret = qemu_loadvm_state(f);
 +    qemu_fclose(f);
 +    if (ret < 0) {
 +        fprintf(logfile, "Error %d while loading savevm file '%s'\n",
 +                ret, name);
 +        goto the_end; 
 +    }
 +
 +#if 0 
 +    /* del tmp file */
 +    if (unlink(name) == -1)
 +        fprintf(stderr, "delete tmp qemu state file failed.\n");
 +#endif
 +
 +
 + the_end:
 +    if (saved_vm_running)
 +        vm_start();
 +}
 +
 +struct qemu_alarm_timer;
 +static int unix_start_timer(struct qemu_alarm_timer *t) { return 0; }
 +static void unix_stop_timer(struct qemu_alarm_timer *t) { }
 +
 +#ifdef CONFIG_STUBDOM
 +#include <netfront.h>
 +static int tap_open(char *ifname, int ifname_size)
 +{
 +    char nodename[64];
 +    static int num = 1; // 0 is for our own TCP/IP networking
 +    snprintf(nodename, sizeof(nodename), "device/vif/%d", num++);
 +    return netfront_tap_open(nodename);
 +}
 +
 +#undef DEFAULT_NETWORK_SCRIPT
 +#define DEFAULT_NETWORK_SCRIPT ""
 +#undef DEFAULT_NETWORK_DOWN_SCRIPT
 +#define DEFAULT_NETWORK_DOWN_SCRIPT ""
 +#endif
 +
diff --cc xenstore.c
index 5cd50638c8e87eecdfeaeeaa1c84ee8bdacaf854,0000000000000000000000000000000000000000..c7f079ac898f3385c224b72d6a8e6cea3f008359
mode 100644,000000..100644
--- /dev/null
@@@ -1,1241 -1,0 +1,1237 @@@
- unsigned long *logdirty_bitmap = NULL;
- unsigned long logdirty_bitmap_size;
- extern int vga_ram_size, bios_size;
 +/*
 + * This file is subject to the terms and conditions of the GNU General
 + * Public License.  See the file "COPYING" in the main directory of
 + * this archive for more details.
 + *
 + * Copyright (C) 2006 Christian Limpach
 + * Copyright (C) 2006 XenSource Ltd.
 + *
 + */
 +
 +#include "qemu-common.h"
 +#include "qemu-char.h"
 +
 +#include "block_int.h"
 +#include <unistd.h>
 +#ifndef CONFIG_STUBDOM
 +#include <sys/ipc.h>
 +#include <sys/shm.h>
 +#endif
 +#include <sys/types.h>
 +#include <sys/stat.h>
 +#include <fcntl.h>
 +#include <assert.h>
 +
 +#include "exec-all.h"
 +#include "sysemu.h"
 +
 +#include "hw.h"
 +#include "pci.h"
 +#include "qemu-timer.h"
 +#include "qemu-xen.h"
 +
 +struct xs_handle *xsh = NULL;
 +static char *media_filename[MAX_DRIVES+1];
 +static QEMUTimer *insert_timer = NULL;
 +
 +#define UWAIT_MAX (30*1000000) /* thirty seconds */
 +#define UWAIT     (100000)     /* 1/10th second  */
 +
 +static int pasprintf(char **buf, const char *fmt, ...)
 +{
 +    va_list ap;
 +    int ret = 0;
 +
 +    if (*buf)
 +        free(*buf);
 +    va_start(ap, fmt);
 +    if (vasprintf(buf, fmt, ap) == -1) {
 +        buf = NULL;
 +        ret = -1;
 +    }
 +    va_end(ap);
 +    return ret;
 +}
 +
 +static void insert_media(void *opaque)
 +{
 +    int i;
 +    BlockDriverState *bs;
 +
 +    for (i = 0; i < MAX_DRIVES + 1; i++) {
 +        bs = drives_table[i].bdrv;
 +        if (media_filename[i] && bs && bs->filename[0] == '\0') {
 +            bdrv_open2(bs, media_filename[i], 0, &bdrv_raw);
 +            pstrcpy(bs->filename, sizeof(bs->filename), media_filename[i]);
 +            free(media_filename[i]);
 +            media_filename[i] = NULL;
 +        }
 +    }
 +}
 +
 +void xenstore_check_new_media_present(int timeout)
 +{
 +
 +    if (insert_timer == NULL)
 +        insert_timer = qemu_new_timer(rt_clock, insert_media, NULL);
 +    qemu_mod_timer(insert_timer, qemu_get_clock(rt_clock) + timeout);
 +}
 +
 +static void waitForDevice(char *fn)
 +{ 
 +    struct stat sbuf;
 +    int status;
 +    int uwait = UWAIT_MAX;
 +
 +    do {
 +        status = stat(fn, &sbuf);
 +        if (!status) break;
 +        usleep(UWAIT);
 +        uwait -= UWAIT;
 +    } while (uwait > 0);
 +
 +    return;
 +}
 +
 +static int any_hdN;
 +
 +static int parse_drive_name(const char *dev, DriveInfo *out) {
 +    /* alway sleaves out->bdrv unchanged */
 +    /* on success, returns 0 and fills in out->type, ->bus, ->unit */
 +    /* if drive name not understood, returns -1 and *out may be garbage */
 +    int ch, max, per_bus;
 +
 +    /* Change xvdN to look like hdN */
 +    if (!any_hdN && !strncmp(dev, "xvd", 3) && strlen(dev) == 4) {
 +        ch = dev[3];
 +        fprintf(logfile, "Using %s for guest's hd%c\n", dev, ch);
 +        out->type = IF_IDE;
 +    } else if (!strncmp(dev, "hd", 2) && strlen(dev) == 3) {
 +        ch = dev[2];
 +        out->type = IF_IDE;
 +    } else if (!strncmp(dev, "sd", 2) && strlen(dev) == 3) {
 +        ch = dev[2];
 +        out->type = IF_SCSI;
 +    } else {
 +        fprintf(stderr, "qemu: ignoring not-understood drive `%s'\n", dev);
 +        return -1;
 +    }
 +
 +    if (out->type == IF_SCSI) {
 +        max = MAX_SCSI_DEVS;
 +        per_bus = max;
 +    } else {
 +        max = 4;
 +        per_bus = 2;
 +    }
 +
 +    ch = ch - 'a';
 +    if (ch >= max) {
 +        fprintf(stderr, "qemu: drive `%s' out of range\n", dev);
 +        return -1;
 +    }
 +
 +    out->bus = ch / per_bus;
 +    out->unit = ch % per_bus;
 +    
 +    return 0;
 +}       
 +
 +static int drive_name_to_index(const char *name) {
 +    DriveInfo tmp;
 +    int ret;
 +
 +    ret = parse_drive_name(name, &tmp);  if (ret) return -1;
 +    ret = drive_get_index(tmp.type, tmp.bus, tmp.unit);
 +    return ret;
 +}
 +
 +static void xenstore_get_backend_path(char **backend, const char *devtype,
 +                                    const char *frontend_dompath,
 +                                    int frontend_domid,
 +                                    const char *inst_danger) {
 +    /* On entry: *backend will be passed to free()
 +     * On succcess: *backend will be from malloc
 +     * On failure: *backend==0
 +     */
 +    char *bpath=0;
 +    char *frontend_path=0;
 +    char *backend_dompath=0;
 +    char *expected_backend=0;
 +    char *frontend_backend_path=0;
 +    char *backend_frontend_path=0;
 +    char *frontend_doublecheck=0;
 +    int len;
 +    const char *frontend_idpath_slash;
 +
 +    /* clear out return value for if we error out */
 +    free(*backend);
 +    *backend = 0;
 +
 +    if (strchr(inst_danger,'/')) {
 +        fprintf(logfile, "xenstore_get_backend_path inst_danger has slash"
 +                " which is forbidden (devtype %s)\n", devtype);
 +      goto out;
 +    }
 +
 +    if (pasprintf(&frontend_path, "%s/device/%s/%s",
 +                  frontend_dompath, devtype, inst_danger)
 +        == -1) goto out;
 +
 +    if (pasprintf(&frontend_backend_path, "%s/backend",
 +                  frontend_path)
 +        == -1) goto out;
 +
 +    bpath = xs_read(xsh, XBT_NULL, frontend_backend_path, &len);
 +
 +    /* now we must check that the backend is intended for use
 +     * by this frontend, since the frontend's /backend xenstore node
 +     * is writeable by the untrustworthy guest. */
 +
 +    backend_dompath = xs_get_domain_path(xsh, domid_backend);
 +    if (!backend_dompath) goto out;
 +    
 +    const char *expected_devtypes[3];
 +    const char **expected_devtype = expected_devtypes;
 +
 +    *expected_devtype++ = devtype;
 +    if (!strcmp(devtype, "vbd")) *expected_devtype++ = "tap";
 +    *expected_devtype = 0;
 +    assert(expected_devtype <
 +           expected_devtypes + ARRAY_SIZE(expected_devtypes));
 +
 +    for (expected_devtype = expected_devtypes;
 +         *expected_devtype;
 +         expected_devtype++) {
 +    
 +        if (pasprintf(&expected_backend, "%s/backend/%s/%lu/%s",
 +                      backend_dompath, *expected_devtype,
 +                      frontend_domid, inst_danger)
 +            == -1) goto out;
 +
 +        if (!strcmp(bpath, expected_backend))
 +            goto found;
 +    }
 +
 +    fprintf(stderr, "frontend `%s' devtype `%s' expected backend `%s'"
 +            " got `%s', ignoring\n",
 +            frontend_path, devtype, expected_backend, bpath);
 +    errno = EINVAL;
 +    goto out;
 +
 + found:
 +
 +    if (pasprintf(&backend_frontend_path, "%s/frontend", bpath)
 +        == -1) goto out;
 +
 +    frontend_doublecheck = xs_read(xsh, XBT_NULL, backend_frontend_path, &len);
 +
 +    if (strcmp(frontend_doublecheck, frontend_path)) {
 +        fprintf(stderr, "frontend `%s' backend `%s' points to other frontend"
 +                " `%s', ignoring\n", frontend_path, bpath, frontend_doublecheck);
 +        errno = EINVAL;
 +        goto out;
 +    }
 +
 +    /* steal bpath */
 +    *backend = bpath;
 +    bpath = 0;
 +
 + out:
 +    free(bpath);
 +    free(frontend_path);
 +    free(backend_dompath);
 +    free(expected_backend);
 +    free(frontend_backend_path);
 +    free(backend_frontend_path);
 +    free(frontend_doublecheck);
 +}
 +
 +const char *xenstore_get_guest_uuid(void) {
 +#ifdef CONFIG_STUBDOM
 +    return 0;
 +#else
 +
 +    static char *already_computed;
 +
 +    xc_domaininfo_t info;
 +    int xch = -1, r, i;
 +    char *p;
 +
 +    if (already_computed)
 +        return already_computed;
 +
 +    xch = xc_interface_open();
 +    if (xch == -1) {
 +        fprintf(logfile, "cannot get uuid - xc_interface_open() failed: %s\n",
 +                strerror(errno));
 +        goto out;
 +    }
 +    r = xc_domain_getinfolist(xch, domid, 1, &info);
 +    if (r != 1) {
 +        fprintf(logfile, "cannot get uuid - xc_domain_getinfolist() failed:"
 +                " %s\n", strerror(errno));
 +        goto out;
 +    }
 +    already_computed = malloc(37);
 +    for (i = 0, p = already_computed; i < 16; i++, p += 2) {
 +        if (i==4 || i==6 || i==8 || i==10)
 +            *p++ = '-';
 +        sprintf(p, "%02x", info.handle[i]);
 +    }
 +    close(xch);
 +    return already_computed;
 +
 + out:
 +    if (xch != -1)
 +        close(xch);
 +    
 +    return 0;
 +#endif
 +}
 +
 +#define DIRECT_PCI_STR_LEN 160
 +char direct_pci_str[DIRECT_PCI_STR_LEN];
 +void xenstore_parse_domain_config(int hvm_domid)
 +{
 +    char **e_danger = NULL;
 +    char *buf = NULL;
 +    char *fpath = NULL, *bpath = NULL,
 +        *dev = NULL, *params = NULL, *drv = NULL;
 +    int i, any_hdN = 0, ret;
 +    unsigned int len, num, hd_index, pci_devid = 0;
 +    BlockDriverState *bs;
 +    BlockDriver *format;
 +
 +    /* paths controlled by untrustworthy guest, and values read from them */
 +    char *danger_path;
 +    char *danger_buf = NULL;
 +    char *danger_type = NULL;
 +
 +    for(i = 0; i < MAX_DRIVES + 1; i++)
 +        media_filename[i] = NULL;
 +
 +    xenstore_get_guest_uuid();
 +
 +    xsh = xs_daemon_open();
 +    if (xsh == NULL) {
 +        fprintf(logfile, "Could not contact xenstore for domain config\n");
 +        return;
 +    }
 +
 +    danger_path = xs_get_domain_path(xsh, hvm_domid);
 +    if (danger_path == NULL) {
 +        fprintf(logfile, "xs_get_domain_path() error\n");
 +        goto out;
 +    }
 +
 +    if (pasprintf(&danger_buf, "%s/device/vbd", danger_path) == -1)
 +        goto out;
 +
 +    e_danger = xs_directory(xsh, XBT_NULL, danger_buf, &num);
 +    if (e_danger == NULL)
 +        num = 0;
 +
 +    for (i = 0; i < num; i++) {
 +        /* read the backend path */
 +        xenstore_get_backend_path(&bpath, "vbd", danger_path, hvm_domid,
 +                                e_danger[i]);
 +        if (bpath == NULL)
 +            continue;    
 +        /* read the name of the device */
 +        if (pasprintf(&buf, "%s/dev", bpath) == -1)
 +            continue;
 +        free(dev);
 +        dev = xs_read(xsh, XBT_NULL, buf, &len);
 +        if (dev == NULL)
 +            continue;
 +        if (!strncmp(dev, "hd", 2)) {
 +            any_hdN = 1;
 +            break;
 +        }
 +    }
 +        
 +    for (i = 0; i < num; i++) {
 +      format = NULL; /* don't know what the format is yet */
 +        /* read the backend path */
 +        xenstore_get_backend_path(&bpath, "vbd", danger_path, hvm_domid, e_danger[i]);
 +        if (bpath == NULL)
 +            continue;
 +        /* read the name of the device */
 +        if (pasprintf(&buf, "%s/dev", bpath) == -1)
 +            continue;
 +        free(dev);
 +        dev = xs_read(xsh, XBT_NULL, buf, &len);
 +        if (dev == NULL)
 +            continue;
 +      if (nb_drives >= MAX_DRIVES) {
 +          fprintf(stderr, "qemu: too many drives, skipping `%s'\n", dev);
 +          continue;
 +      }
 +      ret = parse_drive_name(dev, &drives_table[nb_drives]);
 +      if (ret)
 +          continue;
 +        /* read the type of the device */
 +        if (pasprintf(&danger_buf, "%s/device/vbd/%s/device-type",
 +                      danger_path, e_danger[i]) == -1)
 +            continue;
 +        free(danger_type);
 +        danger_type = xs_read(xsh, XBT_NULL, danger_buf, &len);
 +        if (pasprintf(&buf, "%s/params", bpath) == -1)
 +            continue;
 +        free(params);
 +        params = xs_read(xsh, XBT_NULL, buf, &len);
 +        if (params == NULL)
 +            continue;
 +        /* read the name of the device */
 +        if (pasprintf(&buf, "%s/type", bpath) == -1)
 +            continue;
 +        free(drv);
 +        drv = xs_read(xsh, XBT_NULL, buf, &len);
 +        if (drv == NULL)
 +            continue;
 +        /* Obtain blktap sub-type prefix */
 +        if (!strcmp(drv, "tap") && params[0]) {
 +            char *offset = strchr(params, ':'); 
 +            if (!offset)
 +                continue ;
 +          free(drv);
 +          drv = malloc(offset - params + 1);
 +          memcpy(drv, params, offset - params);
 +          drv[offset - params] = '\0';
 +          if (!strcmp(drv, "aio"))
 +              /* qemu does aio anyway if it can */
 +              format = &bdrv_raw;
 +            memmove(params, offset+1, strlen(offset+1)+1 );
 +            fprintf(logfile, "Strip off blktap sub-type prefix to %s (drv '%s')\n", params, drv); 
 +        }
 +        /* Prefix with /dev/ if needed */
 +        if (!strcmp(drv, "phy") && params[0] != '/') {
 +            char *newparams = malloc(5 + strlen(params) + 1);
 +            sprintf(newparams, "/dev/%s", params);
 +            free(params);
 +            params = newparams;
 +          format = &bdrv_raw;
 +        }
 +
 +#if 0
 +      /* Phantom VBDs are disabled because the use of paths
 +       * from guest-controlled areas in xenstore is unsafe.
 +       * Hopefully if they are really needed for something
 +       * someone will shout and then we will find out what for.
 +       */
 +        /* 
 +         * check if device has a phantom vbd; the phantom is hooked
 +         * to the frontend device (for ease of cleanup), so lookup 
 +         * the frontend device, and see if there is a phantom_vbd
 +         * if there is, we will use resolution as the filename
 +         */
 +        if (pasprintf(&danger_buf, "%s/device/vbd/%s/phantom_vbd", path, e_danger[i]) == -1)
 +            continue;
 +        free(danger_fpath);
 +        danger_fpath = xs_read(xsh, XBT_NULL, danger_buf, &len);
 +        if (danger_fpath) {
 +            if (pasprintf(&danger_buf, "%s/dev", danger_fpath) == -1)
 +                continue;
 +            free(params);
 +          params_danger = xs_read(xsh, XBT_NULL, danger_buf , &len);
 +            DANGER DANGER params is supposedly trustworthy but here
 +                        we read it from untrusted part of xenstore
 +            if (params) {
 +                /* 
 +                 * wait for device, on timeout silently fail because we will 
 +                 * fail to open below
 +                 */
 +                waitForDevice(params);
 +            }
 +        }
 +#endif
 +
 +        bs = bdrv_new(dev);
 +        /* check if it is a cdrom */
 +        if (danger_type && !strcmp(danger_type, "cdrom")) {
 +            bdrv_set_type_hint(bs, BDRV_TYPE_CDROM);
 +            if (pasprintf(&buf, "%s/params", bpath) != -1)
 +                xs_watch(xsh, buf, dev);
 +        }
 +
 +        /* open device now if media present */
 +#ifdef CONFIG_STUBDOM
 +        if (pasprintf(&danger_buf, "%s/device/vbd/%s", danger_path, e_danger[i]) == -1)
 +            continue;
 +      if (bdrv_open2(bs, danger_buf, 0 /* snapshot */, &bdrv_vbd) == 0) {
 +          pstrcpy(bs->filename, sizeof(bs->filename), params);
 +      } else
 +#endif
 +
 +        if (params[0]) {
 +          if (!format) {
 +              if (!drv) {
 +                  fprintf(stderr, "qemu: type (image format) not specified for vbd '%s' or image '%s'\n", buf, params);
 +                  continue;
 +              }
 +              if (!strcmp(drv,"qcow")) {
 +                  /* autoguess qcow vs qcow2 */
 +              } else if (!strcmp(drv,"file")) {
 +                  format = &bdrv_raw;
 +              } else if (!strcmp(drv,"phy")) {
 +                  format = &bdrv_raw;
 +              } else {
 +                  format = bdrv_find_format(drv);
 +                  if (!format) {
 +                      fprintf(stderr, "qemu: type (image format) '%s' unknown for vbd '%s' or image '%s'\n", drv, buf, params);
 +                      continue;
 +                  }
 +              }
 +          }
 +            pstrcpy(bs->filename, sizeof(bs->filename), params);
 +            if (bdrv_open2(bs, params, 0 /* snapshot */, format) < 0)
 +                fprintf(stderr, "qemu: could not open vbd '%s' or hard disk image '%s' (drv '%s' format '%s')\n", buf, params, drv ? drv : "?", format ? format->format_name : "0");
 +        }
 +
 +      drives_table[nb_drives].bdrv = bs;
 +      nb_drives++;
 +
 +    }
 +
 +#ifdef CONFIG_STUBDOM
 +    if (pasprintf(&danger_buf, "%s/device/vkbd", danger_path) == -1)
 +        goto out;
 +
 +    free(e_danger);
 +    e_danger = xs_directory(xsh, XBT_NULL, danger_buf, &num);
 +
 +    if (e_danger) {
 +        for (i = 0; i < num; i++) {
 +            if (pasprintf(&danger_buf, "%s/device/vkbd/%s", danger_path, e_danger[i]) == -1)
 +                continue;
 +            xenfb_connect_vkbd(danger_buf);
 +        }
 +    }
 +
 +    if (pasprintf(&danger_buf, "%s/device/vfb", danger_path) == -1)
 +        goto out;
 +
 +    free(e_danger);
 +    e_danger = xs_directory(xsh, XBT_NULL, danger_buf, &num);
 +
 +    if (e_danger) {
 +        for (i = 0; i < num; i++) {
 +            if (pasprintf(&danger_buf, "%s/device/vfb/%s", danger_path, e_danger[i]) == -1)
 +                continue;
 +            xenfb_connect_vfb(danger_buf);
 +        }
 +    }
 +#endif
 +
 +
 +    /* Set a watch for log-dirty requests from the migration tools */
 +    if (pasprintf(&buf, "/local/domain/0/device-model/%u/logdirty/next-active",
 +                  domid) != -1) {
 +        xs_watch(xsh, buf, "logdirty");
 +        fprintf(logfile, "Watching %s\n", buf);
 +    }
 +
 +    /* Set a watch for suspend requests from the migration tools */
 +    if (pasprintf(&buf, 
 +                  "/local/domain/0/device-model/%u/command", domid) != -1) {
 +        xs_watch(xsh, buf, "dm-command");
 +        fprintf(logfile, "Watching %s\n", buf);
 +    }
 +
 +    /* get the pci pass-through parameter */
 +    if (pasprintf(&buf, "/local/domain/0/backend/pci/%u/%u/num_devs",
 +                  hvm_domid, pci_devid) == -1)
 +        goto out;
 +
 +    free(params);
 +    params = xs_read(xsh, XBT_NULL, buf, &len);
 +    if (params == NULL)
 +        goto out;
 +    num = atoi(params);
 +
 +    for ( i = 0; i < num; i++ ) {
 +        if (pasprintf(&buf, "/local/domain/0/backend/pci/%u/%u/dev-%d",
 +                    hvm_domid, pci_devid, i) != -1) {
 +            free(dev);
 +            dev = xs_read(xsh, XBT_NULL, buf, &len);
 +
 +            if ( strlen(dev) + strlen(direct_pci_str) > DIRECT_PCI_STR_LEN ) {
 +                fprintf(stderr, "qemu: too many pci pass-through devices\n");
 +                memset(direct_pci_str, 0, DIRECT_PCI_STR_LEN);
 +                goto out;
 +            }
 +
 +            /* append to direct_pci_str */
 +            if ( dev ) {
 +                strcat(direct_pci_str, dev);
 +                strcat(direct_pci_str, "-");
 +            }
 +        }
 +    }
 +
 + out:
 +    free(danger_type);
 +    free(params);
 +    free(dev);
 +    free(bpath);
 +    free(buf);
 +    free(danger_buf);
 +    free(danger_path);
 +    free(e_danger);
 +    free(drv);
 +    return;
 +}
 +
 +int xenstore_fd(void)
 +{
 +    if (xsh)
 +        return xs_fileno(xsh);
 +    return -1;
 +}
 +
 +void xenstore_process_logdirty_event(void)
 +{
 +#ifdef CONFIG_STUBDOM
 +    /* XXX we just can't use shm. */
 +    return;
 +#else
 +    char *act;
 +    static char *active_path = NULL;
 +    static char *next_active_path = NULL;
 +    static char *seg = NULL;
 +    unsigned int len;
 +    int i;
 +
 +    if (!seg) {
 +        char *path = NULL, *key_ascii, key_terminated[17] = {0,};
 +        key_t key;
 +        int shmid;
 +
 +        /* Find and map the shared memory segment for log-dirty bitmaps */
 +        if (pasprintf(&path, 
 +                      "/local/domain/0/device-model/%u/logdirty/key", 
 +                      domid) == -1) {
 +            fprintf(logfile, "Log-dirty: out of memory\n");
 +            exit(1);
 +        }
 +        
 +        key_ascii = xs_read(xsh, XBT_NULL, path, &len);
 +        free(path);
 +
 +        if (!key_ascii) 
 +            /* No key yet: wait for the next watch */
 +            return;
 +
 +        strncpy(key_terminated, key_ascii, 16);
 +        free(key_ascii);
 +        key = (key_t) strtoull(key_terminated, NULL, 16);
 +
 +        /* Figure out how bit the log-dirty bitmaps are */
 +        logdirty_bitmap_size = xc_memory_op(xc_handle, 
 +                                            XENMEM_maximum_gpfn, &domid) + 1;
 +        logdirty_bitmap_size = ((logdirty_bitmap_size + HOST_LONG_BITS - 1)
 +                                / HOST_LONG_BITS); /* longs */
 +        logdirty_bitmap_size *= sizeof (unsigned long); /* bytes */
 +
 +        /* Map the shared-memory segment */
 +        fprintf(logfile, "%s: key=%16.16llx size=%lu\n", __FUNCTION__,
 +                (unsigned long long)key, logdirty_bitmap_size);
 +        shmid = shmget(key, 2 * logdirty_bitmap_size, S_IRUSR|S_IWUSR);
 +        if (shmid == -1) {
 +            fprintf(logfile, "Log-dirty: shmget failed: segment %16.16llx "
 +                    "(%s)\n", (unsigned long long)key, strerror(errno));
 +            exit(1);
 +        }
 +
 +        seg = shmat(shmid, NULL, 0);
 +        if (seg == (void *)-1) {
 +            fprintf(logfile, "Log-dirty: shmat failed: segment %16.16llx "
 +                    "(%s)\n", (unsigned long long)key, strerror(errno));
 +            exit(1);
 +        }
 +
 +        fprintf(logfile, "Log-dirty: mapped segment at %p\n", seg);
 +
 +        /* Double-check that the bitmaps are the size we expect */
 +        if (logdirty_bitmap_size != *(uint32_t *)seg) {
 +            fprintf(logfile, "Log-dirty: got %u, calc %lu\n", 
 +                    *(uint32_t *)seg, logdirty_bitmap_size);
 +            /* Stale key: wait for next watch */
 +            shmdt(seg);
 +            seg = NULL;
 +            return;
 +        }
 +
 +        /* Remember the paths for the next-active and active entries */
 +        if (pasprintf(&active_path, 
 +                      "/local/domain/0/device-model/%u/logdirty/active",
 +                      domid) == -1) {
 +            fprintf(logfile, "Log-dirty: out of memory\n");
 +            exit(1);
 +        }
 +        if (pasprintf(&next_active_path, 
 +                      "/local/domain/0/device-model/%u/logdirty/next-active",
 +                      domid) == -1) {
 +            fprintf(logfile, "Log-dirty: out of memory\n");
 +            exit(1);
 +        }
 +    }
 +
 +    fprintf(logfile, "Triggered log-dirty buffer switch\n");
 +    
 +    /* Read the required active buffer from the store */
 +    act = xs_read(xsh, XBT_NULL, next_active_path, &len);
 +    if (!act) {
 +        fprintf(logfile, "Log-dirty: can't read next-active\n");
 +        exit(1);
 +    }
 +
 +    /* Switch buffers */
 +    i = act[0] - '0';
 +    if (i != 0 && i != 1) {
 +        fprintf(logfile, "Log-dirty: bad next-active entry: %s\n", act);
 +        exit(1);
 +    }
 +    logdirty_bitmap = (unsigned long *)(seg + i * logdirty_bitmap_size);
 +
 +    /* Ack that we've switched */
 +    xs_write(xsh, XBT_NULL, active_path, act, len);
 +    free(act);
 +#endif
 +}
 +
 +
 +/* Accept state change commands from the control tools */
 +static void xenstore_process_dm_command_event(void)
 +{
 +    char *path = NULL, *command = NULL, *par = NULL;
 +    unsigned int len;
 +
 +    if (pasprintf(&path, 
 +                  "/local/domain/0/device-model/%u/command", domid) == -1) {
 +        fprintf(logfile, "out of memory reading dm command\n");
 +        goto out;
 +    }
 +    command = xs_read(xsh, XBT_NULL, path, &len);
 +    if (!command)
 +        goto out;
 +    
 +    if (!strncmp(command, "save", len)) {
 +        fprintf(logfile, "dm-command: pause and save state\n");
 +        xen_pause_requested = 1;
 +    } else if (!strncmp(command, "continue", len)) {
 +        fprintf(logfile, "dm-command: continue after state save\n");
 +        xen_pause_requested = 0;
 +#ifdef CONFIG_PASSTHROUGH
 +    } else if (!strncmp(command, "pci-rem", len)) {
 +        fprintf(logfile, "dm-command: hot remove pass-through pci dev \n");
 +
 +        if (pasprintf(&path, 
 +                      "/local/domain/0/device-model/%u/parameter", domid) == -1) {
 +            fprintf(logfile, "out of memory reading dm command parameter\n");
 +            goto out;
 +        }
 +        par = xs_read(xsh, XBT_NULL, path, &len);
 +        if (!par)
 +            goto out;
 +
 +        do_pci_del(par);
 +        free(par);
 +    } else if (!strncmp(command, "pci-ins", len)) {
 +        fprintf(logfile, "dm-command: hot insert pass-through pci dev \n");
 +
 +        if (pasprintf(&path, 
 +                      "/local/domain/0/device-model/%u/parameter", domid) == -1) {
 +            fprintf(logfile, "out of memory reading dm command parameter\n");
 +            goto out;
 +        }
 +        par = xs_read(xsh, XBT_NULL, path, &len);
 +        if (!par)
 +            goto out;
 +
 +        do_pci_add(par);
 +        free(par);
 +#endif
 +    } else {
 +        fprintf(logfile, "dm-command: unknown command\"%*s\"\n", len, command);
 +    }
 +
 + out:
 +    free(path);
 +    free(command);
 +}
 +
 +void xenstore_record_dm(char *subpath, char *state)
 +{
 +    char *path = NULL;
 +
 +    if (pasprintf(&path, 
 +                  "/local/domain/0/device-model/%u/%s", domid, subpath) == -1) {
 +        fprintf(logfile, "out of memory recording dm \n");
 +        goto out;
 +    }
 +    if (!xs_write(xsh, XBT_NULL, path, state, strlen(state)))
 +        fprintf(logfile, "error recording dm \n");
 +
 + out:
 +    free(path);
 +}
 +
 +void xenstore_record_dm_state(char *state)
 +{
 +    xenstore_record_dm("state", state);
 +}
 +
 +void xenstore_process_event(void *opaque)
 +{
 +    char **vec, *offset, *bpath = NULL, *buf = NULL, *drv = NULL, *image = NULL;
 +    unsigned int len, num, hd_index;
 +
 +    vec = xs_read_watch(xsh, &num);
 +    if (!vec)
 +        return;
 +
 +    if (!strcmp(vec[XS_WATCH_TOKEN], "logdirty")) {
 +        xenstore_process_logdirty_event();
 +        goto out;
 +    }
 +
 +    if (!strcmp(vec[XS_WATCH_TOKEN], "dm-command")) {
 +        xenstore_process_dm_command_event();
 +        goto out;
 +    }
 +
 +    if (strncmp(vec[XS_WATCH_TOKEN], "hd", 2) ||
 +        strlen(vec[XS_WATCH_TOKEN]) != 3)
 +        goto out;
 +
 +    hd_index = drive_name_to_index(vec[XS_WATCH_TOKEN]);
 +    if (hd_index == -1) {
 +      fprintf(stderr,"medium change watch on `%s' -"
 +              " unknown device, ignored\n", vec[XS_WATCH_TOKEN]);
 +      goto out;
 +    }
 +
 +    image = xs_read(xsh, XBT_NULL, vec[XS_WATCH_PATH], &len);
 +
 +    fprintf(stderr,"medium change watch on `%s' (index: %d): %s\n",
 +          vec[XS_WATCH_TOKEN], hd_index, image ? image : "<none>");
 +
 +    if (image == NULL)
 +        goto out;  /* gone */
 +
 +    /* Strip off blktap sub-type prefix */
 +    bpath = strdup(vec[XS_WATCH_PATH]); 
 +    if (bpath == NULL)
 +        goto out;
 +    if ((offset = strrchr(bpath, '/')) != NULL) 
 +        *offset = '\0';
 +    if (pasprintf(&buf, "%s/type", bpath) == -1) 
 +        goto out;
 +    drv = xs_read(xsh, XBT_NULL, buf, &len);
 +    if (drv && !strcmp(drv, "tap") && ((offset = strchr(image, ':')) != NULL))
 +        memmove(image, offset+1, strlen(offset+1)+1);
 +
 +    if (!strcmp(image, drives_table[hd_index].bdrv->filename))
 +        goto out;  /* identical */
 +
 +    drives_table[hd_index].bdrv->filename[0] = '\0';
 +    bdrv_close(drives_table[hd_index].bdrv);
 +    if (media_filename[hd_index]) {
 +        free(media_filename[hd_index]);
 +        media_filename[hd_index] = NULL;
 +    }
 +
 +    if (image[0]) {
 +        media_filename[hd_index] = strdup(image);
 +        xenstore_check_new_media_present(5000);
 +    }
 +
 + out:
 +    free(drv);
 +    free(buf);
 +    free(bpath);
 +    free(image);
 +    free(vec);
 +}
 +
 +void xenstore_write_vncport(int display)
 +{
 +    char *buf = NULL, *path;
 +    char *portstr = NULL;
 +
 +    if (xsh == NULL)
 +        return;
 +
 +    path = xs_get_domain_path(xsh, domid);
 +    if (path == NULL) {
 +        fprintf(logfile, "xs_get_domain_path() error\n");
 +        goto out;
 +    }
 +
 +    if (pasprintf(&buf, "%s/console/vnc-port", path) == -1)
 +        goto out;
 +
 +    if (pasprintf(&portstr, "%d", display) == -1)
 +        goto out;
 +
 +    if (xs_write(xsh, XBT_NULL, buf, portstr, strlen(portstr)) == 0)
 +        fprintf(logfile, "xs_write() vncport failed\n");
 +
 + out:
 +    free(portstr);
 +    free(buf);
 +}
 +
 +void xenstore_write_vslots(char *vslots)
 +{
 +    char *path = NULL;
 +    int pci_devid = 0;
 +
 +    if (pasprintf(&path, 
 +                  "/local/domain/0/backend/pci/%u/%u/vslots", domid, pci_devid) == -1) {
 +        fprintf(logfile, "out of memory when updating vslots.\n");
 +        goto out;
 +    }
 +    if (!xs_write(xsh, XBT_NULL, path, vslots, strlen(vslots)))
 +        fprintf(logfile, "error updating vslots \n");
 +
 + out:
 +    free(path);
 +}
 +
 +void xenstore_read_vncpasswd(int domid, char *pwbuf, size_t pwbuflen)
 +{
 +    char *buf = NULL, *path, *uuid = NULL, *passwd = NULL;
 +    unsigned int i, len;
 +
 +    pwbuf[0] = '\0';
 +
 +    if (xsh == NULL)
 +        return;
 +
 +    path = xs_get_domain_path(xsh, domid);
 +    if (path == NULL) {
 +        fprintf(logfile, "xs_get_domain_path() error. domid %d.\n", domid);
 +        return;
 +    }
 +
 +    pasprintf(&buf, "%s/vm", path);
 +    free(path);
 +    uuid = xs_read(xsh, XBT_NULL, buf, &len);
 +    if (uuid == NULL) {
 +        fprintf(logfile, "xs_read(): uuid get error. %s.\n", buf);
 +        free(buf);
 +        return;
 +    }
 +
 +    pasprintf(&buf, "%s/vncpasswd", uuid);
 +    free(uuid);
 +    passwd = xs_read(xsh, XBT_NULL, buf, &len);
 +    if (passwd == NULL) {
 +        fprintf(logfile, "xs_read(): vncpasswd get error. %s.\n", buf);
 +        free(buf);
 +        return;
 +    }
 +
 +    if (len >= pwbuflen)
 +    {
 +        fprintf(logfile, "xenstore_read_vncpasswd(): truncated password to avoid buffer overflow\n");
 +        len = pwbuflen - 1;
 +    }
 +
 +    for (i=0; i<len; i++)
 +        pwbuf[i] = passwd[i];
 +    pwbuf[len] = '\0';
 +    passwd[0] = '\0';
 +    if (xs_write(xsh, XBT_NULL, buf, passwd, 1) == 0)
 +        fprintf(logfile, "xs_write() vncpasswd failed.\n");
 +
 +    free(passwd);
 +    free(buf);
 +}
 +
 +
 +/*
 + * get all device instances of a certain type
 + */
 +char **xenstore_domain_get_devices_danger(struct xs_handle *handle,
 +                                   const char *devtype, unsigned int *num)
 +{
 +    char *path;
 +    char *buf = NULL;
 +    char **e  = NULL;
 +
 +    path = xs_get_domain_path(handle, domid);
 +    if (path == NULL)
 +        goto out;
 +
 +    if (pasprintf(&buf, "%s/device/%s", path,devtype) == -1)
 +        goto out;
 +
 +    e = xs_directory(handle, XBT_NULL, buf, num);
 +
 + out:
 +    free(path);
 +    free(buf);
 +    return e;
 +}
 +
 +/*
 + * Check whether a domain has devices of the given type
 + */
 +int xenstore_domain_has_devtype_danger(struct xs_handle *handle,
 +                                    const char *devtype)
 +{
 +    int rc = 0;
 +    unsigned int num;
 +    char **e = xenstore_domain_get_devices_danger(handle, devtype, &num);
 +    if (e)
 +        rc = 1;
 +    free(e);
 +    return rc;
 +}
 +
 +/*
 + * Function that creates a path to a variable of an instance of a
 + * certain device
 + */
 +static char *get_device_variable_path(const char *devtype,
 +                                      const char *inst_danger,
 +                                      const char *var)
 +{
 +    char *buf = NULL;
 +    if (strchr(inst_danger,'/')) {
 +        fprintf(logfile, "get_device_variable_path inst_danger has slash"
 +                " which is forbidden (devtype %s)\n", devtype);
 +        return NULL;
 +    }
 +
 +    if (pasprintf(&buf, "/local/domain/%d/backend/%s/%d/%s/%s",
 +                  domid_backend,
 +                  devtype,
 +                  domid,
 +                  inst_danger /* safe now */,
 +                  var) == -1) {
 +        free(buf);
 +        buf = NULL;
 +    }
 +    return buf;
 +}
 +
 +char *xenstore_backend_read_variable(struct xs_handle *handle,
 +                                     const char *devtype,
 +                                     const char *inst_danger,
 +                                     const char *var)
 +{
 +    char *value = NULL;
 +    char *buf = NULL;
 +    unsigned int len;
 +
 +    buf = get_device_variable_path(devtype, inst_danger, var);
 +    if (NULL == buf)
 +        goto out;
 +
 +    value = xs_read(handle, XBT_NULL, buf, &len);
 +
 +    free(buf);
 +
 + out:
 +    return value;
 +}
 +
 +/*
 +  Read the hotplug status variable from the backend given the type
 +  of device and its instance.
 +*/
 +char *xenstore_read_hotplug_status(struct xs_handle *handle,
 +                                   const char *devtype,
 +                                   const char *inst_danger)
 +{
 +    return xenstore_backend_read_variable(handle, devtype, inst_danger,
 +                                          "hotplug-status");
 +}
 +
 +/*
 +   Subscribe to the hotplug status of a device given the type of device and
 +   its instance.
 +   In case an error occurrs, a negative number is returned.
 + */
 +int xenstore_subscribe_to_hotplug_status(struct xs_handle *handle,
 +                                         const char *devtype,
 +                                         const char *inst_danger,
 +                                         const char *token)
 +{
 +    int rc = 0;
 +    char *path = get_device_variable_path(devtype, inst_danger, "hotplug-status");
 +
 +    if (path == NULL)
 +        return -1;
 +
 +    if (0 == xs_watch(handle, path, token))
 +        rc = -2;
 +
 +    free(path);
 +
 +    return rc;
 +}
 +
 +/*
 + * Unsubscribe from a subscription to the status of a hotplug variable of
 + * a device.
 + */
 +int xenstore_unsubscribe_from_hotplug_status(struct xs_handle *handle,
 +                                             const char *devtype,
 +                                             const char *inst_danger,
 +                                             const char *token)
 +{
 +    int rc = 0;
 +    char *path;
 +    path = get_device_variable_path(devtype, inst_danger, "hotplug-status");
 +    if (path == NULL)
 +        return -1;
 +
 +    if (0 == xs_unwatch(handle, path, token))
 +        rc = -2;
 +
 +    free(path);
 +
 +    return rc;
 +}
 +
 +static char *xenstore_vm_key_path(int domid, char *key) {
 +    const char *uuid;
 +    char *buf = NULL;
 +    
 +    if (xsh == NULL)
 +        return NULL;
 +
 +    uuid = xenstore_get_guest_uuid();
 +    if (!uuid) return NULL;
 +
 +    if (pasprintf(&buf, "/vm/%s/%s", uuid, key) == -1)
 +        return NULL;
 +    return buf;
 +}
 +
 +char *xenstore_vm_read(int domid, char *key, unsigned int *len)
 +{
 +    char *path = NULL, *value = NULL;
 +
 +    path = xenstore_vm_key_path(domid, key);
 +
 +    value = xs_read(xsh, XBT_NULL, path, len);
 +    if (value == NULL) {
 +        fprintf(logfile, "xs_read(%s): read error\n", path);
 +        goto out;
 +    }
 +
 + out:
 +    free(path);
 +    return value;
 +}
 +
 +int xenstore_vm_write(int domid, char *key, char *value)
 +{
 +    char *path = NULL;
 +    int rc = -1;
 +
 +    path = xenstore_vm_key_path(domid, key);
 +
 +    rc = xs_write(xsh, XBT_NULL, path, value, strlen(value));
 +    if (rc == 0) {
 +        fprintf(logfile, "xs_write(%s, %s): write error\n", path, key);
 +        goto out;
 +    }
 +
 + out:
 +    free(path);
 +    return rc;
 +}
 +
 +
 +/*
 + * Create a store entry for a device (e.g., monitor, serial/parallel lines).
 + * The entry is <domain-path><storeString>/tty and the value is the name
 + * of the pty associated with the device.
 + */
 +static int store_dev_info(const char *devName, int domid,
 +                          CharDriverState *cState, const char *storeString)
 +{
 +#ifdef CONFIG_STUBDOM
 +    fprintf(logfile, "can't store dev %s name for domid %d in %s from a stub domain\n", devName, domid, storeString);
 +    return ENOSYS;
 +#else
 +    int xc_handle;
 +    struct xs_handle *xs;
 +    char *path;
 +    char *newpath;
 +    char *pts;
 +    char namebuf[128];
 +    int ret;
 +
 +    /*
 +     * Only continue if we're talking to a pty
 +     */
 +    if (!cState->chr_getname) return 0;
 +    ret = cState->chr_getname(cState, namebuf, sizeof(namebuf));
 +    if (ret < 0) {
 +        fprintf(logfile, "ptsname failed (for '%s'): %s\n",
 +                storeString, strerror(errno));
 +        return 0;
 +    }
 +    if (memcmp(namebuf, "pty ", 4)) return 0;
 +    pts = namebuf + 4;
 +
 +    /* We now have everything we need to set the xenstore entry. */
 +    xs = xs_daemon_open();
 +    if (xs == NULL) {
 +        fprintf(logfile, "Could not contact XenStore\n");
 +        return -1;
 +    }
 +
 +    xc_handle = xc_interface_open();
 +    if (xc_handle == -1) {
 +        fprintf(logfile, "xc_interface_open() error\n");
 +        return -1;
 +    }
 +
 +    path = xs_get_domain_path(xs, domid);
 +    if (path == NULL) {
 +        fprintf(logfile, "xs_get_domain_path() error\n");
 +        return -1;
 +    }
 +    newpath = realloc(path, (strlen(path) + strlen(storeString) +
 +                             strlen("/tty") + 1));
 +    if (newpath == NULL) {
 +        free(path); /* realloc errors leave old block */
 +        fprintf(logfile, "realloc error\n");
 +        return -1;
 +    }
 +    path = newpath;
 +
 +    strcat(path, storeString);
 +    strcat(path, "/tty");
 +    if (!xs_write(xs, XBT_NULL, path, pts, strlen(pts))) {
 +        fprintf(logfile, "xs_write for '%s' fail", storeString);
 +        return -1;
 +    }
 +
 +    free(path);
 +    xs_daemon_close(xs);
 +    close(xc_handle);
 +
 +    return 0;
 +#endif
 +}
 +
 +void xenstore_store_serial_port_info(int i, CharDriverState *chr,
 +                                   const char *devname) {
 +    char buf[16];
 +
 +    snprintf(buf, sizeof(buf), "/serial/%d", i);
 +    store_dev_info(devname, domid, chr, buf);
 +    if (i == 0) /* serial 0 is also called the console */
 +        store_dev_info(devname, domid, chr, "/console");
 +}