WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-devel

[Xen-devel] [RFC] Add stubdomain support

To: xen-devel@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-devel] [RFC] Add stubdomain support
From: Samuel Thibault <samuel.thibault@xxxxxxxxxxxxx>
Date: Mon, 11 Feb 2008 17:40:38 +0000
Delivery-date: Mon, 11 Feb 2008 09:42:19 -0800
Envelope-to: www-data@xxxxxxxxxxxxxxxxxx
List-help: <mailto:xen-devel-request@lists.xensource.com?subject=help>
List-id: Xen developer discussion <xen-devel.lists.xensource.com>
List-post: <mailto:xen-devel@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-devel>, <mailto:xen-devel-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-devel>, <mailto:xen-devel-request@lists.xensource.com?subject=unsubscribe>
Mail-followup-to: Samuel Thibault <samuel.thibault@xxxxxxxxxxxxx>, xen-devel@xxxxxxxxxxxxxxxxxxx
Sender: xen-devel-bounces@xxxxxxxxxxxxxxxxxxx
User-agent: Mutt/1.5.12-2006-07-14
Hello,

At last, here is the big patch that adds the stubdomain support.  I
guess some reviewing will be needed before commiting it.



Add stubdomain support.

- Setup a xen-elf cross-compilation environment in stubdom/cross-root
- Add a POSIX layer on top of Mini-OS by linking against the newlib C library
  and lwIP, and implementing the Unixish part in mini-os/lib/sys.c
- Cross-compile zlib and libpci too.
- Add an xs.h-compatible layer on top of Mini-OS' xenbus.
- Cross-compile libxc with an additional xc_minios.c and a few things disabled.
- Cross-compile ioemu with an additional block-vbd, but without sound, tpm and
  other details.  A few hacks are needed:
  - Align ide and scsi buffers at least on sector size to permit direct
  transmission to the block backend. While we are at it, just page-align it
  to possibly save a segment. Also, limit the scsi buffer size because of
  limitations of the block paravirtualization protocol.
  - Allocate big tables dynamically rather that letting them go to bss: when
  Mini-OS gets installed in memory, bss is not lazily allocated, and doing so
  during Mini-OS is unnecessarily trick while we can simply use malloc.
- Have the domain killer send SIGHUP to the device-model script, allow the
  script 10s to clean up, and if still not dead, send SIGKILL.
- Had to change the Mini-OS compilation somehow, so as to export Mini-OS
  compilation flags to the Makefiles of libxc and ioemu.

Signed-off-by: Samuel Thibault <samuel.thibault@xxxxxxxxxxxxx>

diff -r 7b0c0ab0566b .hgignore
--- a/.hgignore Mon Feb 11 14:55:33 2008 +0000
+++ b/.hgignore Mon Feb 11 17:16:12 2008 +0000
@@ -221,6 +221,17 @@
 ^tools/xm-test/lib/XmTestLib/config.py$
 ^tools/xm-test/lib/XmTestReport/xmtest.py$
 ^tools/xm-test/tests/.*\.test$
+^stubdom/binutils.*$
+^stubdom/cross-root.*$
+^stubdom/gcc.*$
+^stubdom/include.*$
+^stubdom/ioemu.*$
+^stubdom/libxc.*$
+^stubdom/lwip.*$
+^stubdom/mini-os.*$
+^stubdom/newlib.*$
+^stubdom/pciutils.*$
+^stubdom/zlib.*$
 ^xen/BLOG$
 ^xen/System.map$
 ^xen/TAGS$
diff -r 7b0c0ab0566b Config.mk
--- a/Config.mk Mon Feb 11 14:55:33 2008 +0000
+++ b/Config.mk Mon Feb 11 17:16:12 2008 +0000
@@ -27,6 +27,14 @@ DESTDIR     ?= /
 
 include $(XEN_ROOT)/config/$(XEN_OS).mk
 include $(XEN_ROOT)/config/$(XEN_TARGET_ARCH).mk
+
+ifeq ($(stubdom),y)
+include $(XEN_ROOT)/extras/mini-os/Config.mk
+CFLAGS += $(DEF_CFLAGS) $(ARCH_CFLAGS)
+CPPFLAGS += $(DEF_CPPFLAGS) $(ARCH_CPPFLAGS) $(extra_incl)
+ASFLAGS += $(DEF_ASFLAGS) $(ARCH_ASFLAGS)
+LDFLAGS += $(DEF_LDFLAGS) $(ARCH_LDFLAGS)
+endif
 
 ifneq ($(EXTRA_PREFIX),)
 EXTRA_INCLUDES += $(EXTRA_PREFIX)/include
diff -r 7b0c0ab0566b extras/mini-os/Config.mk
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/extras/mini-os/Config.mk  Mon Feb 11 17:16:12 2008 +0000
@@ -0,0 +1,75 @@
+# Set mini-os root path, used in mini-os.mk.
+MINI-OS_ROOT=$(XEN_ROOT)/extras/mini-os
+export MINI-OS_ROOT
+
+ifeq ($(XEN_TARGET_ARCH),x86_32)
+export pae ?= y
+endif
+libc = $(stubdom)
+
+XEN_INTERFACE_VERSION := 0x00030205
+export XEN_INTERFACE_VERSION
+
+# Try to find out the architecture family TARGET_ARCH_FAM.
+# First check whether x86_... is contained (for x86_32, x86_32y, x86_64).
+# If not x86 then use $(XEN_TARGET_ARCH) -> for ia64, ...
+ifeq ($(findstring x86_,$(XEN_TARGET_ARCH)),x86_)
+TARGET_ARCH_FAM = x86
+else
+TARGET_ARCH_FAM = $(XEN_TARGET_ARCH)
+endif
+
+# The architecture family directory below mini-os.
+TARGET_ARCH_DIR := arch/$(TARGET_ARCH_FAM)
+
+# Export these variables for possible use in architecture dependent makefiles.
+export TARGET_ARCH_DIR
+export TARGET_ARCH_FAM
+export XEN_TARGET_X86_PAE 
+
+# This is used for architecture specific links.
+# This can be overwritten from arch specific rules.
+ARCH_LINKS =
+
+# The path pointing to the architecture specific header files.
+ARCH_INC := $(TARGET_ARCH_FAM)
+
+# For possible special header directories.
+# This can be overwritten from arch specific rules.
+EXTRA_INC = $(ARCH_INC)        
+
+# Include the architecture family's special makerules.
+# This must be before include minios.mk!
+include $(MINI-OS_ROOT)/$(TARGET_ARCH_DIR)/arch.mk
+
+extra_incl := $(foreach dir,$(EXTRA_INC),-I$(MINI-OS_ROOT)/include/$(dir))
+
+DEF_CPPFLAGS += -I$(MINI-OS_ROOT)/include
+
+ifeq ($(stubdom),y)
+DEF_CPPFLAGS += -DCONFIG_STUBDOM
+endif
+
+ifeq ($(libc),y)
+DEF_CPPFLAGS += -DHAVE_LIBC
+DEF_CPPFLAGS += -I$(MINI-OS_ROOT)/include/posix
+endif
+
+ifneq ($(LWIPDIR),)
+lwip=y
+DEF_CPPFLAGS += -DHAVE_LWIP
+DEF_CPPFLAGS += -I$(LWIPDIR)/src/include
+DEF_CPPFLAGS += -I$(LWIPDIR)/src/include/ipv4
+endif
+
+ifneq ($(QEMUDIR),)
+qemu=y
+endif
+
+ifneq ($(CAMLDIR),)
+caml=y
+endif
+
+ifeq ($(pae),y)
+DEF_CPPFLAGS += -DCONFIG_X86_PAE
+endif
diff -r 7b0c0ab0566b extras/mini-os/Makefile
--- a/extras/mini-os/Makefile   Mon Feb 11 14:55:33 2008 +0000
+++ b/extras/mini-os/Makefile   Mon Feb 11 17:16:12 2008 +0000
@@ -4,54 +4,11 @@
 # Makefile and a arch.mk.
 #
 
-XEN_ROOT = ../..
+export XEN_ROOT = ../..
 include $(XEN_ROOT)/Config.mk
 
-XEN_INTERFACE_VERSION := 0x00030205
-export XEN_INTERFACE_VERSION
-
-# Set TARGET_ARCH
-override TARGET_ARCH := $(XEN_TARGET_ARCH)
-
-# Set mini-os root path, used in mini-os.mk.
-MINI-OS_ROOT=$(PWD)
-export MINI-OS_ROOT
-
-# Try to find out the architecture family TARGET_ARCH_FAM.
-# First check whether x86_... is contained (for x86_32, x86_32y, x86_64).
-# If not x86 then use $(TARGET_ARCH) -> for ia64, ...
-ifeq ($(findstring x86_,$(TARGET_ARCH)),x86_)
-TARGET_ARCH_FAM = x86
-else
-TARGET_ARCH_FAM = $(TARGET_ARCH)
-endif
-
-# The architecture family directory below mini-os.
-TARGET_ARCH_DIR := arch/$(TARGET_ARCH_FAM)
-
-# Export these variables for possible use in architecture dependent makefiles.
-export TARGET_ARCH
-export TARGET_ARCH_DIR
-export TARGET_ARCH_FAM
-export XEN_TARGET_X86_PAE 
-
-# This is used for architecture specific links.
-# This can be overwritten from arch specific rules.
-ARCH_LINKS =
-
-# For possible special header directories.
-# This can be overwritten from arch specific rules.
-EXTRA_INC =
-
-# Include the architecture family's special makerules.
-# This must be before include minios.mk!
-include $(TARGET_ARCH_DIR)/arch.mk
-
-ifneq ($(LWIPDIR),)
-lwip=y
-DEF_CFLAGS += -DHAVE_LWIP
-DEF_CFLAGS += -I$(LWIPDIR)/src/include
-DEF_CFLAGS += -I$(LWIPDIR)/src/include/ipv4
+ifneq ($(stubdom),y)
+include Config.mk
 endif
 
 # Include common mini-os makerules.
@@ -63,7 +20,7 @@ include minios.mk
 # Define some default flags for linking.
 LDLIBS := 
 LDARCHLIB := -L$(TARGET_ARCH_DIR) -l$(ARCH_LIB_NAME)
-LDFLAGS_FINAL := -T $(TARGET_ARCH_DIR)/minios-$(TARGET_ARCH).lds
+LDFLAGS_FINAL := -T $(TARGET_ARCH_DIR)/minios-$(XEN_TARGET_ARCH).lds
 
 # Prefix for global API names. All other symbols are localised before
 # linking with EXTRA_OBJS.
@@ -112,14 +69,38 @@ lwip.a: $(LWO)
        $(AR) cqs $@ $^
 
 OBJS += lwip.a
+endif
 
-OBJS := $(filter-out $(LWO), $(OBJS))
+OBJS := $(filter-out lwip%.o $(LWO), $(OBJS))
+
+ifeq ($(caml),y)
+CAMLLIB = $(shell ocamlc -where)
+OBJS += $(CAMLDIR)/caml.o
+OBJS += $(CAMLLIB)/libasmrun.a
+CFLAGS += -I$(CAMLLIB)
+LDLIBS += -lm
 else
-OBJS := $(filter-out daytime.o lwip%.o, $(OBJS))
+OBJS := $(filter-out main-caml.o, $(OBJS))
+endif
+
+ifeq ($(qemu),y)
+OBJS += $(QEMUDIR)/i386-dm-stubdom/qemu.a $(QEMUDIR)/i386-dm-stubdom/libqemu.a
+CFLAGS += -DCONFIG_QEMU
+endif
+
+ifeq ($(libc),y)
+LDLIBS += -L$(XEN_ROOT)/stubdom/libxc -lxenctrl -lxenguest
+LDLIBS += -lpci
+LDLIBS += -lz
+LDLIBS += -lc
+endif
+
+ifneq ($(caml)-$(qemu)-$(lwip),--y)
+OBJS := $(filter-out daytime.o, $(OBJS))
 endif
 
 $(TARGET): links $(OBJS) arch_lib
-       $(LD) -r $(LDFLAGS) $(HEAD_OBJ) $(OBJS) $(LDARCHLIB) -o $@.o
+       $(LD) -r $(LDFLAGS) $(HEAD_OBJ) $(OBJS) $(LDARCHLIB) $(LDLIBS) -o $@.o
        $(OBJCOPY) -w -G $(GLOBAL_PREFIX)* -G _start $@.o $@.o
        $(LD) $(LDFLAGS) $(LDFLAGS_FINAL) $@.o $(EXTRA_OBJS) -o $@
        gzip -f -9 -c $@ >$@.gz
diff -r 7b0c0ab0566b extras/mini-os/arch/ia64/Makefile
--- a/extras/mini-os/arch/ia64/Makefile Mon Feb 11 14:55:33 2008 +0000
+++ b/extras/mini-os/arch/ia64/Makefile Mon Feb 11 17:16:12 2008 +0000
@@ -4,6 +4,8 @@
 
 XEN_ROOT = ../../../..
 include $(XEN_ROOT)/Config.mk
+
+include ../../Config.mk
 
 include arch.mk
 include ../../minios.mk
@@ -41,7 +43,7 @@ ARCH_OBJS += __divdi3.o
 
 GEN_OFF_SRC := gen_off.c
 GEN_OFF_ASM := gen_off.s
-GEN_OFF_H   := $(ARCH_INC)/offsets.h
+GEN_OFF_H   := $(MINI-OS_ROOT)/include/$(ARCH_INC)/offsets.h
 
 all: $(ARCH_LIB)
 
diff -r 7b0c0ab0566b extras/mini-os/arch/ia64/minios-ia64.lds
--- a/extras/mini-os/arch/ia64/minios-ia64.lds  Mon Feb 11 14:55:33 2008 +0000
+++ b/extras/mini-os/arch/ia64/minios-ia64.lds  Mon Feb 11 17:16:12 2008 +0000
@@ -40,6 +40,18 @@ SECTIONS
   .rodata.str1.8 : AT(ADDR(.rodata.str1.8) - (((5<<(61))+0x100000000) - (1 << 
20)))
   { *(.rodata.str1.8) }
 
+  /* newlib initialization functions */
+  . = ALIGN(64 / 8);
+  PROVIDE (__preinit_array_start = .);
+  .preinit_array     : { *(.preinit_array) }
+  PROVIDE (__preinit_array_end = .);
+  PROVIDE (__init_array_start = .);
+  .init_array     : { *(.init_array) }
+  PROVIDE (__init_array_end = .);
+  PROVIDE (__fini_array_start = .);
+  .fini_array     : { *(.fini_array) }
+  PROVIDE (__fini_array_end = .);
+
   .IA_64.unwind_info : AT(ADDR(.IA_64.unwind_info) - (((5<<(61))+0x100000000) 
- (1 << 20)))
   { *(.IA_64.unwind_info) }
 
diff -r 7b0c0ab0566b extras/mini-os/arch/ia64/mm.c
--- a/extras/mini-os/arch/ia64/mm.c     Mon Feb 11 14:55:33 2008 +0000
+++ b/extras/mini-os/arch/ia64/mm.c     Mon Feb 11 17:16:12 2008 +0000
@@ -42,6 +42,14 @@ extern uint64_t _text[], _etext[], _end[
 extern uint64_t _text[], _etext[], _end[], kstack[], phys_start[];
 
 uint64_t kernstart, kernend, kernsize, kernpstart, kernpend;
+
+#ifdef HAVE_LIBC
+uint8_t _heap[512 * 1024];
+unsigned long heap = (unsigned long)_heap,
+              brk = (unsigned long)_heap,
+              heap_mapped = (unsigned long)_heap + sizeof(_heap),
+              heap_end = (unsigned long)_heap + sizeof(_heap);
+#endif
 
 /* Print the available memory chunks. */
 static void
diff -r 7b0c0ab0566b extras/mini-os/arch/x86/Makefile
--- a/extras/mini-os/arch/x86/Makefile  Mon Feb 11 14:55:33 2008 +0000
+++ b/extras/mini-os/arch/x86/Makefile  Mon Feb 11 17:16:12 2008 +0000
@@ -5,13 +5,14 @@
 
 XEN_ROOT = ../../../..
 include $(XEN_ROOT)/Config.mk
+include ../../Config.mk
 
 # include arch.mk has to be before mini-os.mk!
 
 include arch.mk
 include ../../minios.mk
 
-# Sources here are all *.c *.S without $(TARGET_ARCH).S
+# Sources here are all *.c *.S without $(XEN_TARGET_ARCH).S
 # This is handled in $(HEAD_ARCH_OBJ)
 ARCH_SRCS := $(wildcard *.c)
 
diff -r 7b0c0ab0566b extras/mini-os/arch/x86/arch.mk
--- a/extras/mini-os/arch/x86/arch.mk   Mon Feb 11 14:55:33 2008 +0000
+++ b/extras/mini-os/arch/x86/arch.mk   Mon Feb 11 17:16:12 2008 +0000
@@ -3,11 +3,11 @@
 # (including x86_32, x86_32y and x86_64).
 #
 
-ifeq ($(TARGET_ARCH),x86_32)
+ifeq ($(XEN_TARGET_ARCH),x86_32)
 ARCH_CFLAGS  := -m32 -march=i686
 ARCH_LDFLAGS := -m elf_i386
 ARCH_ASFLAGS := -m32
-EXTRA_INC += $(TARGET_ARCH_FAM)/$(TARGET_ARCH)
+EXTRA_INC += $(TARGET_ARCH_FAM)/$(XEN_TARGET_ARCH)
 EXTRA_SRC += arch/$(EXTRA_INC)
 
 ifeq ($(XEN_TARGET_X86_PAE),y)
@@ -16,12 +16,12 @@ endif
 endif
 endif
 
-ifeq ($(TARGET_ARCH),x86_64)
+ifeq ($(XEN_TARGET_ARCH),x86_64)
 ARCH_CFLAGS := -m64 -mno-red-zone -fno-reorder-blocks
 ARCH_CFLAGS += -fno-asynchronous-unwind-tables
 ARCH_ASFLAGS := -m64
 ARCH_LDFLAGS := -m elf_x86_64
-EXTRA_INC += $(TARGET_ARCH_FAM)/$(TARGET_ARCH)
+EXTRA_INC += $(TARGET_ARCH_FAM)/$(XEN_TARGET_ARCH)
 EXTRA_SRC += arch/$(EXTRA_INC)
 endif
 
diff -r 7b0c0ab0566b extras/mini-os/arch/x86/minios-x86_32.lds
--- a/extras/mini-os/arch/x86/minios-x86_32.lds Mon Feb 11 14:55:33 2008 +0000
+++ b/extras/mini-os/arch/x86/minios-x86_32.lds Mon Feb 11 17:16:12 2008 +0000
@@ -15,6 +15,18 @@ SECTIONS
   .rodata : { *(.rodata) *(.rodata.*) }
   . = ALIGN(4096);
   _erodata = .;
+
+  /* newlib initialization functions */
+  . = ALIGN(32 / 8);
+  PROVIDE (__preinit_array_start = .);
+  .preinit_array     : { *(.preinit_array) }
+  PROVIDE (__preinit_array_end = .);
+  PROVIDE (__init_array_start = .);
+  .init_array     : { *(.init_array) }
+  PROVIDE (__init_array_end = .);
+  PROVIDE (__fini_array_start = .);
+  .fini_array     : { *(.fini_array) }
+  PROVIDE (__fini_array_end = .);
 
   .data : {                    /* Data */
        *(.data)
diff -r 7b0c0ab0566b extras/mini-os/arch/x86/minios-x86_64.lds
--- a/extras/mini-os/arch/x86/minios-x86_64.lds Mon Feb 11 14:55:33 2008 +0000
+++ b/extras/mini-os/arch/x86/minios-x86_64.lds Mon Feb 11 17:16:12 2008 +0000
@@ -15,6 +15,18 @@ SECTIONS
   .rodata : { *(.rodata) *(.rodata.*) }
   . = ALIGN(4096);
   _erodata = .;
+
+  /* newlib initialization functions */
+  . = ALIGN(64 / 8);
+  PROVIDE (__preinit_array_start = .);
+  .preinit_array     : { *(.preinit_array) }
+  PROVIDE (__preinit_array_end = .);
+  PROVIDE (__init_array_start = .);
+  .init_array     : { *(.init_array) }
+  PROVIDE (__init_array_end = .);
+  PROVIDE (__fini_array_start = .);
+  .fini_array     : { *(.fini_array) }
+  PROVIDE (__fini_array_end = .);
 
   .data : {                    /* Data */
        *(.data)
diff -r 7b0c0ab0566b extras/mini-os/arch/x86/mm.c
--- a/extras/mini-os/arch/x86/mm.c      Mon Feb 11 14:55:33 2008 +0000
+++ b/extras/mini-os/arch/x86/mm.c      Mon Feb 11 17:16:12 2008 +0000
@@ -448,6 +448,15 @@ static unsigned long demand_map_area_sta
 #define DEMAND_MAP_PAGES ((2ULL << 30) / PAGE_SIZE)
 #endif
 
+#ifdef HAVE_LIBC
+unsigned long heap, brk, heap_mapped, heap_end;
+#ifdef __x86_64__
+#define HEAP_PAGES ((128ULL << 30) / PAGE_SIZE)
+#else
+#define HEAP_PAGES ((1ULL << 30) / PAGE_SIZE)
+#endif
+#endif
+
 void arch_init_demand_mapping_area(unsigned long cur_pfn)
 {
     cur_pfn++;
@@ -455,6 +464,14 @@ void arch_init_demand_mapping_area(unsig
     demand_map_area_start = (unsigned long) pfn_to_virt(cur_pfn);
     cur_pfn += DEMAND_MAP_PAGES;
     printk("Demand map pfns at %lx-%lx.\n", demand_map_area_start, 
pfn_to_virt(cur_pfn));
+
+#ifdef HAVE_LIBC
+    cur_pfn++;
+    heap_mapped = brk = heap = (unsigned long) pfn_to_virt(cur_pfn);
+    cur_pfn += HEAP_PAGES;
+    heap_end = (unsigned long) pfn_to_virt(cur_pfn);
+    printk("Heap resides at %lx-%lx.\n", brk, heap_end);
+#endif
 }
 
 #define MAP_BATCH ((STACK_SIZE / 2) / sizeof(mmu_update_t))
diff -r 7b0c0ab0566b extras/mini-os/blkfront.c
--- a/extras/mini-os/blkfront.c Mon Feb 11 14:55:33 2008 +0000
+++ b/extras/mini-os/blkfront.c Mon Feb 11 17:16:12 2008 +0000
@@ -14,6 +14,10 @@
 #include <blkfront.h>
 #include <lib.h>
 #include <fcntl.h>
+
+#ifndef HAVE_LIBC
+#define strtoul simple_strtoul
+#endif
 
 /* Note: we generally don't need to disable IRQs since we hardly do anything in
  * the interrupt handler.  */
@@ -49,6 +53,10 @@ struct blkfront_dev {
     int mode;
     int barrier;
     int flush;
+
+#ifdef HAVE_LIBC
+    int fd;
+#endif
 };
 
 static inline int xenblk_rxidx(RING_IDX idx)
@@ -58,6 +66,12 @@ static inline int xenblk_rxidx(RING_IDX 
 
 void blkfront_handler(evtchn_port_t port, struct pt_regs *regs, void *data)
 {
+#ifdef HAVE_LIBC
+    struct blkfront_dev *dev = data;
+    int fd = dev->fd;
+
+    files[fd].read = 1;
+#endif
     wake_up(&blkfront_queue);
 }
 
@@ -148,7 +162,7 @@ done:
 
     printk("backend at %s\n", dev->backend);
 
-    dev->handle = simple_strtoul(strrchr(nodename, '/')+1, NULL, 0);
+    dev->handle = strtoul(strrchr(nodename, '/')+1, NULL, 0);
 
     {
         char path[strlen(dev->backend) + 1 + 19 + 1];
@@ -322,12 +336,16 @@ moretodo:
     {
        rsp = RING_GET_RESPONSE(&dev->ring, cons);
 
+        if (rsp->status != BLKIF_RSP_OKAY)
+            printk("block error %d for op %d\n", rsp->status, rsp->operation);
+
         switch (rsp->operation) {
         case BLKIF_OP_READ:
         case BLKIF_OP_WRITE:
         {
             struct blkfront_aiocb *aiocbp = (void*) (uintptr_t) rsp->id;
             int j;
+
             for (j = 0; j < aiocbp->n; j++)
                 gnttab_end_access(aiocbp->gref[j]);
 
@@ -365,6 +383,12 @@ static void blkfront_push_operation(stru
     i = dev->ring.req_prod_pvt;
     req = RING_GET_REQUEST(&dev->ring, i);
     req->operation = op;
+    req->nr_segments = 0;
+    req->handle = dev->handle;
+    /* Not used */
+    req->id = 0;
+    /* Not needed anyway, but the backend will check it */
+    req->sector_number = 0;
     dev->ring.req_prod_pvt = i + 1;
     wmb();
     RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&dev->ring, notify);
@@ -375,11 +399,13 @@ void blkfront_sync(struct blkfront_dev *
 {
     unsigned long flags;
 
-    if (dev->barrier == 1)
-        blkfront_push_operation(dev, BLKIF_OP_WRITE_BARRIER);
+    if (dev->mode == O_RDWR) {
+        if (dev->barrier == 1)
+            blkfront_push_operation(dev, BLKIF_OP_WRITE_BARRIER);
 
-    if (dev->flush == 1)
-        blkfront_push_operation(dev, BLKIF_OP_FLUSH_DISKCACHE);
+        if (dev->flush == 1)
+            blkfront_push_operation(dev, BLKIF_OP_FLUSH_DISKCACHE);
+    }
 
     /* Note: This won't finish if another thread enqueues requests.  */
     local_irq_save(flags);
@@ -397,3 +423,13 @@ void blkfront_sync(struct blkfront_dev *
     remove_waiter(w);
     local_irq_restore(flags);
 }
+
+#ifdef HAVE_LIBC
+int blkfront_open(struct blkfront_dev *dev)
+{
+    dev->fd = alloc_fd(FTYPE_BLK);
+    printk("blk_open(%s) -> %d\n", dev->nodename, dev->fd);
+    files[dev->fd].blk.dev = dev;
+    return dev->fd;
+}
+#endif
diff -r 7b0c0ab0566b extras/mini-os/include/arch/cc.h
--- a/extras/mini-os/include/arch/cc.h  Mon Feb 11 14:55:33 2008 +0000
+++ b/extras/mini-os/include/arch/cc.h  Mon Feb 11 17:16:12 2008 +0000
@@ -54,7 +54,14 @@ extern void lwip_die(char *fmt, ...);
 #include <errno.h>
 
 /*   Not required by the docs, but needed for network-order calculations */
+#ifdef HAVE_LIBC
+#include <machine/endian.h>
+#ifndef BIG_ENDIAN
+#error endian.h does not define byte order
+#endif
+#else
 #include <endian.h>
+#endif
 
 #include <inttypes.h>
 #define S16_F PRIi16
diff -r 7b0c0ab0566b extras/mini-os/include/byteswap.h
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/extras/mini-os/include/byteswap.h Mon Feb 11 17:16:12 2008 +0000
@@ -0,0 +1,22 @@
+#ifndef _BYTESWAP_H_
+#define _BYTESWAP_H_
+
+/* Unfortunately not provided by newlib.  */
+#define bswap_16(x) \
+    ((((x) & 0xff00) >> 8) | (((x) & 0xff) << 8))
+
+#define bswap_32(x) \
+    ((((x) & 0xff000000) >> 24) | (((x) & 0x00ff0000) >>  8) | \
+     (((x) & 0x0000ff00) <<  8) | (((x) & 0x000000ff) << 24))
+
+#define bswap_64(x) \
+    ((((x) & 0xff00000000000000ULL) >> 56) | \
+     (((x) & 0x00ff000000000000ULL) >> 40) | \
+     (((x) & 0x0000ff0000000000ULL) >> 24) | \
+     (((x) & 0x000000ff00000000ULL) >>  8) | \
+     (((x) & 0x00000000ff000000ULL) <<  8) | \
+     (((x) & 0x0000000000ff0000ULL) << 24) | \
+     (((x) & 0x000000000000ff00ULL) << 40) | \
+     (((x) & 0x00000000000000ffULL) << 56))
+
+#endif /* _BYTESWAP_H */
diff -r 7b0c0ab0566b extras/mini-os/include/console.h
--- a/extras/mini-os/include/console.h  Mon Feb 11 14:55:33 2008 +0000
+++ b/extras/mini-os/include/console.h  Mon Feb 11 17:16:12 2008 +0000
@@ -36,7 +36,9 @@
 #ifndef _LIB_CONSOLE_H_
 #define _LIB_CONSOLE_H_
 
+#include<os.h>
 #include<traps.h>
+#include<stdarg.h>
 
 void print(int direct, const char *fmt, va_list args);
 void printk(const char *fmt, ...);
@@ -48,5 +50,6 @@ void xencons_tx(void);
 void xencons_tx(void);
 
 void init_console(void);
+void console_print(char *data, int length);
 
 #endif /* _LIB_CONSOLE_H_ */
diff -r 7b0c0ab0566b extras/mini-os/include/errno.h
--- a/extras/mini-os/include/errno.h    Mon Feb 11 14:55:33 2008 +0000
+++ b/extras/mini-os/include/errno.h    Mon Feb 11 17:16:12 2008 +0000
@@ -107,4 +107,11 @@
 #define        EOWNERDEAD      130     /* Owner died */
 #define        ENOTRECOVERABLE 131     /* State not recoverable */
 
+#ifdef HAVE_LIBC
+#include <sched.h>
+extern int errno;
+#define ERRNO
+#define errno (get_current()->reent._errno)
 #endif
+
+#endif
diff -r 7b0c0ab0566b extras/mini-os/include/fcntl.h
--- a/extras/mini-os/include/fcntl.h    Mon Feb 11 14:55:33 2008 +0000
+++ b/extras/mini-os/include/fcntl.h    Mon Feb 11 17:16:12 2008 +0000
@@ -86,4 +86,7 @@ struct flock64 {
 
 #define F_LINUX_SPECIFIC_BASE  1024
 */
+
+int open(const char *path, int flags, ...);
+int fcntl(int fd, int cmd, ...);
 #endif
diff -r 7b0c0ab0566b extras/mini-os/include/fs.h
--- a/extras/mini-os/include/fs.h       Mon Feb 11 14:55:33 2008 +0000
+++ b/extras/mini-os/include/fs.h       Mon Feb 11 17:16:12 2008 +0000
@@ -22,6 +22,7 @@ struct fs_import
     struct semaphore reqs_sem;      /* Accounts requests resource           */
 };
 
+extern struct fs_import *fs_import;
 
 void init_fs_frontend(void);
 
diff -r 7b0c0ab0566b extras/mini-os/include/ia64/arch_mm.h
--- a/extras/mini-os/include/ia64/arch_mm.h     Mon Feb 11 14:55:33 2008 +0000
+++ b/extras/mini-os/include/ia64/arch_mm.h     Mon Feb 11 17:16:12 2008 +0000
@@ -35,11 +35,12 @@
 #define virt_to_mfn(x) virt_to_pfn(x)
 #define virtual_to_mfn(x)      (ia64_tpa((uint64_t)(x)) >> PAGE_SHIFT)
 
-#define STACK_SIZE_PAGE_ORDER   1
+#define STACK_SIZE_PAGE_ORDER   2
 #define STACK_SIZE              (PAGE_SIZE * (1 << STACK_SIZE_PAGE_ORDER))
 
 #define map_frames(f, n) map_frames_ex(f, n, 1, 0, 1, DOMID_SELF, 0, 0)
 /* TODO */
 #define map_zero(n, a) map_frames_ex(NULL, n, 0, 0, a, DOMID_SELF, 0, 0)
+#define do_map_zero(start, n) ((void)0)
 
 #endif /* __ARCH_MM_H__ */
diff -r 7b0c0ab0566b extras/mini-os/include/ia64/os.h
--- a/extras/mini-os/include/ia64/os.h  Mon Feb 11 14:55:33 2008 +0000
+++ b/extras/mini-os/include/ia64/os.h  Mon Feb 11 17:16:12 2008 +0000
@@ -292,9 +292,12 @@ do {                                                       
                \
 /* This is a barrier for the compiler only, NOT the processor! */
 #define barrier() __asm__ __volatile__("": : :"memory")
 
+#ifndef __barriers_defined
+#define __barriers_defined
 #define mb()   ia64_mf()
 #define rmb()  mb()
 #define wmb()  mb()
+#endif
 
 
 #define BUG()  \
diff -r 7b0c0ab0566b extras/mini-os/include/lib.h
--- a/extras/mini-os/include/lib.h      Mon Feb 11 14:55:33 2008 +0000
+++ b/extras/mini-os/include/lib.h      Mon Feb 11 17:16:12 2008 +0000
@@ -57,6 +57,8 @@
 
 #include <stdarg.h>
 #include <stddef.h>
+#include <xen/xen.h>
+#include <xen/event_channel.h>
 
 #ifdef HAVE_LIBC
 #include <stdio.h>
@@ -103,6 +105,8 @@ char  *strdup(const char *s);
 
 int rand(void);
 
+#include <xenbus.h>
+
 #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
 
 struct kvec {
@@ -126,4 +130,59 @@ do {                                    
 /* Consistency check as much as possible. */
 void sanity_check(void);
 
+#ifdef HAVE_LIBC
+enum fd_type {
+    FTYPE_NONE = 0,
+    FTYPE_CONSOLE,
+    FTYPE_FILE,
+    FTYPE_XENBUS,
+    FTYPE_EVTCHN,
+    FTYPE_SOCKET,
+    FTYPE_TAP,
+    FTYPE_BLK,
+};
+
+#define MAX_EVTCHN_PORTS 16
+
+extern struct file {
+    enum fd_type type;
+    union {
+       struct {
+            /* lwIP fd */
+           int fd;
+       } socket;
+       struct {
+            /* FS import fd */
+           int fd;
+           off_t offset;
+       } file;
+       struct {
+            /* To each event channel FD is associated a series of ports which
+             * wakes select for this FD. */
+            struct {
+                evtchn_port_t port;
+                volatile unsigned long pending;
+                int bound;
+            } ports[MAX_EVTCHN_PORTS];
+       } evtchn;
+       struct {
+           struct netfront_dev *dev;
+       } tap;
+       struct {
+           struct blkfront_dev *dev;
+       } blk;
+        struct {
+            /* To each xenbus FD is associated a queue of watch events for this
+             * FD.  */
+            struct xenbus_event *volatile events;
+        } xenbus;
+    };
+    volatile int read; /* maybe available for read */
+} files[];
+
+int alloc_fd(enum fd_type type);
+void close_all_files(void);
+extern struct thread *main_thread;
+#endif
+
 #endif /* _LIB_H_ */
diff -r 7b0c0ab0566b extras/mini-os/include/linux/types.h
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/extras/mini-os/include/linux/types.h      Mon Feb 11 17:16:12 2008 +0000
@@ -0,0 +1,5 @@
+#ifndef _LINUX_TYPES_H_
+#define _LINUX_TYPES_H_
+#include <types.h>
+typedef u64 __u64;
+#endif /* _LINUX_TYPES_H_ */
diff -r 7b0c0ab0566b extras/mini-os/include/mm.h
--- a/extras/mini-os/include/mm.h       Mon Feb 11 14:55:33 2008 +0000
+++ b/extras/mini-os/include/mm.h       Mon Feb 11 17:16:12 2008 +0000
@@ -61,5 +61,8 @@ void *map_frames_ex(unsigned long *f, un
 void *map_frames_ex(unsigned long *f, unsigned long n, unsigned long stride,
        unsigned long increment, unsigned long alignment, domid_t id,
        int may_fail, unsigned long prot);
+#ifdef HAVE_LIBC
+extern unsigned long heap, brk, heap_mapped, heap_end;
+#endif
 
 #endif /* _MM_H_ */
diff -r 7b0c0ab0566b extras/mini-os/include/netfront.h
--- a/extras/mini-os/include/netfront.h Mon Feb 11 14:55:33 2008 +0000
+++ b/extras/mini-os/include/netfront.h Mon Feb 11 17:16:12 2008 +0000
@@ -6,6 +6,10 @@ struct netfront_dev *init_netfront(char 
 struct netfront_dev *init_netfront(char *nodename, void (*netif_rx)(unsigned 
char *data, int len), unsigned char rawmac[6]);
 void netfront_xmit(struct netfront_dev *dev, unsigned char* data,int len);
 void shutdown_netfront(struct netfront_dev *dev);
+#ifdef HAVE_LIBC
+int netfront_tap_open(char *nodename);
+ssize_t netfront_receive(struct netfront_dev *dev, unsigned char *data, size_t 
len);
+#endif
 
 extern struct wait_queue_head netfront_queue;
 
diff -r 7b0c0ab0566b extras/mini-os/include/posix/dirent.h
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/extras/mini-os/include/posix/dirent.h     Mon Feb 11 17:16:12 2008 +0000
@@ -0,0 +1,24 @@
+#ifndef _POSIX_DIRENT_H
+#define _POSIX_DIRENT_H
+
+#include <sys/types.h>
+
+struct dirent {
+        char *d_name;
+};
+
+typedef struct {
+        struct dirent dirent;
+        char *name;
+        int32_t offset;
+        char **entries;
+        int32_t curentry;
+        int32_t nbentries;
+        int has_more;
+} DIR;
+
+DIR *opendir(const char *name);
+struct dirent *readdir(DIR *dir);
+int closedir(DIR *dir);
+
+#endif /* _POSIX_DIRENT_H */
diff -r 7b0c0ab0566b extras/mini-os/include/posix/limits.h
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/extras/mini-os/include/posix/limits.h     Mon Feb 11 17:16:12 2008 +0000
@@ -0,0 +1,8 @@
+#ifndef _POSIX_LIMITS_H
+#define _POSIX_LIMITS_H
+
+#include_next <limits.h>
+
+#define PATH_MAX PAGE_SIZE
+
+#endif /* _POSIX_LIMITS_H */
diff -r 7b0c0ab0566b extras/mini-os/include/posix/netdb.h
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/extras/mini-os/include/posix/netdb.h      Mon Feb 11 17:16:12 2008 +0000
@@ -0,0 +1,9 @@
+#ifndef _POSIX_NETDB_H_
+#define _POSIX_NETDB_H_
+
+struct hostent {
+    char *h_addr;
+};
+#define gethostbyname(buf) NULL
+
+#endif /* _POSIX_NETDB_H_ */
diff -r 7b0c0ab0566b extras/mini-os/include/posix/netinet/in.h
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/extras/mini-os/include/posix/netinet/in.h Mon Feb 11 17:16:12 2008 +0000
@@ -0,0 +1,7 @@
+#ifndef _POSIX_SYS_IN_H_
+#define _POSIX_SYS_IN_H_
+
+#include <fcntl.h>
+#include <lwip/sockets.h>
+
+#endif /* _POSIX_SYS_IN_H_ */
diff -r 7b0c0ab0566b extras/mini-os/include/posix/netinet/tcp.h
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/extras/mini-os/include/posix/netinet/tcp.h        Mon Feb 11 17:16:12 
2008 +0000
@@ -0,0 +1,6 @@
+#ifndef _POSIX_SYS_TCP_H_
+#define _POSIX_SYS_TCP_H_
+
+#include <lwip/tcp.h>
+
+#endif /* _POSIX_SYS_TCP_H_ */
diff -r 7b0c0ab0566b extras/mini-os/include/posix/pthread.h
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/extras/mini-os/include/posix/pthread.h    Mon Feb 11 17:16:12 2008 +0000
@@ -0,0 +1,19 @@
+#ifndef _POSIX_PTHREAD_H
+#define _POSIX_PTHREAD_H
+
+/* Let's be single-threaded for now.  */
+
+typedef void *pthread_key_t;
+typedef struct {} pthread_mutex_t, pthread_once_t;
+#define PTHREAD_MUTEX_INITIALIZER {}
+#define PTHREAD_ONCE_INIT {}
+static inline int pthread_mutex_lock(pthread_mutex_t *mutex) { return 0; }
+static inline int pthread_mutex_unlock(pthread_mutex_t *mutex) { return 0; }
+static inline int pthread_key_create(pthread_key_t *key, void 
(*destr_function)(void*)) { *key = NULL; return 0; }
+static inline int pthread_setspecific(pthread_key_t *key, const void *pointer) 
{ *key = (void*) pointer; return 0; }
+static inline void *pthread_getspecific(pthread_key_t *key) { return *key; }
+static inline int pthread_once(pthread_once_t *once_control, void 
(*init_routine)(void)) { init_routine(); return 0; }
+
+#define __thread
+
+#endif /* _POSIX_PTHREAD_H */
diff -r 7b0c0ab0566b extras/mini-os/include/posix/stdlib.h
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/extras/mini-os/include/posix/stdlib.h     Mon Feb 11 17:16:12 2008 +0000
@@ -0,0 +1,8 @@
+#ifndef _POSIX_STDLIB_H
+#define _POSIX_STDLIB_H
+
+#include_next <stdlib.h>
+
+#define realpath(p,r) strcpy(r,p)
+
+#endif /* _POSIX_STDLIB_H */
diff -r 7b0c0ab0566b extras/mini-os/include/posix/strings.h
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/extras/mini-os/include/posix/strings.h    Mon Feb 11 17:16:12 2008 +0000
@@ -0,0 +1,8 @@
+#ifndef _POSIX_STRINGS_H
+#define _POSIX_STRINGS_H
+
+#include <string.h>
+
+#define bzero(ptr, size) (memset((ptr), '\0', (size)), (void) 0)
+
+#endif /* _POSIX_STRINGS_H */
diff -r 7b0c0ab0566b extras/mini-os/include/posix/sys/ioctl.h
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/extras/mini-os/include/posix/sys/ioctl.h  Mon Feb 11 17:16:12 2008 +0000
@@ -0,0 +1,16 @@
+#ifndef _POSIX_SYS_IOCTL_H
+#define _POSIX_SYS_IOCTL_H
+
+int ioctl(int fd, int request, ...);
+
+#define _IOC_NONE 0
+#define _IOC_WRITE 1
+#define _IOC_READ 2
+
+#define _IOC(rw, class, n, size) \
+       (((rw   ) << 30) | \
+        ((class) << 22) | \
+        ((n    ) << 14) | \
+        ((size ) << 0))
+
+#endif /* _POSIX_SYS_IOCTL_H */
diff -r 7b0c0ab0566b extras/mini-os/include/posix/sys/mman.h
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/extras/mini-os/include/posix/sys/mman.h   Mon Feb 11 17:16:12 2008 +0000
@@ -0,0 +1,19 @@
+#ifndef _POSIX_SYS_MMAN_H
+#define _POSIX_SYS_MMAN_H
+
+#define PROT_READ      0x1
+#define PROT_WRITE     0x2
+#define PROT_EXEC      0x4
+
+#define MAP_SHARED     0x01
+#define MAP_PRIVATE    0x02
+#define MAP_ANON       0x20
+
+#define MAP_FAILED     ((void*)0)
+
+void *mmap(void *start, size_t length, int prot, int flags, int fd, off_t 
offset);
+int munmap(void *start, size_t length);
+#define munlock(addr, len) ((void)addr, (void)len, 0)
+#define mlock(addr, len) ((void)addr, (void)len, 0)
+
+#endif /* _POSIX_SYS_MMAN_H */
diff -r 7b0c0ab0566b extras/mini-os/include/posix/sys/select.h
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/extras/mini-os/include/posix/sys/select.h Mon Feb 11 17:16:12 2008 +0000
@@ -0,0 +1,7 @@
+#ifndef _POSIX_SELECT_H
+#define _POSIX_SELECT_H
+
+#include <sys/time.h>
+int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, 
struct timeval *timeout);
+
+#endif /* _POSIX_SELECT_H */
diff -r 7b0c0ab0566b extras/mini-os/include/posix/sys/socket.h
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/extras/mini-os/include/posix/sys/socket.h Mon Feb 11 17:16:12 2008 +0000
@@ -0,0 +1,31 @@
+#ifndef _POSIX_SYS_SOCKET_H_
+#define _POSIX_SYS_SOCKET_H_
+
+#include <fcntl.h>
+#include <lwip/sockets.h>
+
+int accept(int s, struct sockaddr *addr, socklen_t *addrlen);
+int bind(int s, struct sockaddr *name, socklen_t namelen);
+int shutdown(int s, int how);
+int getpeername (int s, struct sockaddr *name, socklen_t *namelen);
+int getsockname (int s, struct sockaddr *name, socklen_t *namelen);
+int getsockopt (int s, int level, int optname, void *optval, socklen_t 
*optlen);
+int setsockopt (int s, int level, int optname, const void *optval, socklen_t 
optlen);
+int close(int s);
+int connect(int s, struct sockaddr *name, socklen_t namelen);
+int listen(int s, int backlog);
+int recv(int s, void *mem, int len, unsigned int flags);
+//int read(int s, void *mem, int len);
+int recvfrom(int s, void *mem, int len, unsigned int flags,
+      struct sockaddr *from, socklen_t *fromlen);
+int send(int s, void *dataptr, int size, unsigned int flags);
+int sendto(int s, void *dataptr, int size, unsigned int flags,
+    struct sockaddr *to, socklen_t tolen);
+int socket(int domain, int type, int protocol);
+//int write(int s, void *dataptr, int size);
+int select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset,
+                struct timeval *timeout);
+//int ioctl(int s, long cmd, void *argp);
+int getsockname(int s, struct sockaddr *name, socklen_t *namelen);
+
+#endif /* _POSIX_SYS_SOCKET_H_ */
diff -r 7b0c0ab0566b extras/mini-os/include/posix/termios.h
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/extras/mini-os/include/posix/termios.h    Mon Feb 11 17:16:12 2008 +0000
@@ -0,0 +1,87 @@
+#ifndef _POSIX_TERMIOS_H
+#define _POSIX_TERMIOS_H
+
+#define NCC 32
+
+struct termios {
+    unsigned long c_iflag;
+    unsigned long c_oflag;
+    unsigned long c_lflag;
+    unsigned long c_cflag;
+    unsigned char c_cc[NCC];
+};
+
+/* modem lines */
+#define TIOCM_DTR      0x002
+#define TIOCM_RTS      0x004
+#define TIOCM_CTS      0x020
+#define TIOCM_CAR      0x040
+#define TIOCM_RI       0x080
+#define TIOCM_DSR      0x100
+
+/* c_iflag */
+#define IGNBRK 0x00000001
+#define BRKINT 0x00000002
+#define IGNPAR 0x00000004
+#define PARMRK 0x00000008
+#define INPCK  0x00000010
+#define ISTRIP 0x00000020
+#define INLCR  0x00000040
+#define IGNCR  0x00000080
+#define ICRNL  0x00000100
+#define IUCLC  0x00000200
+#define IXON   0x00000400
+#define IXANY  0x00000800
+#define IXOFF  0x00001000
+#define IMAXBEL        0x00002000
+#define IUTF8  0x00004000
+
+/* c_oflag */
+#define OPOST  0x00000001
+#define OLCUC  0x00000002
+#define ONLCR  0x00000004
+#define OCRNL  0x00000008
+#define ONOCR  0x00000010
+#define ONLRET 0x00000020
+#define OFILL  0x00000040
+#define OFDEL  0x00000080
+
+/* c_lflag */
+#define ISIG   0x00000001
+#define ICANON 0x00000002
+#define XCASE  0x00000004
+#define ECHO   0x00000008
+#define ECHOE  0x00000010
+#define ECHOK  0x00000020
+#define ECHONL 0x00000040
+#define NOFLSH 0x00000080
+#define TOSTOP 0x00000100
+#define ECHOCTL        0x00000200
+#define ECHOPRT        0x00000400
+#define ECHOKE 0x00000800
+#define FLUSHO 0x00002000
+#define PENDIN 0x00004000
+#define IEXTEN 0x00008000
+
+/* c_cflag */
+#define CSIZE  0x00000030
+#define CS8    0x00000030
+#define CSTOPB 0x00000040
+#define CREAD  0x00000080
+#define PARENB 0x00000100
+#define PARODD 0x00000200
+#define HUPCL  0x00000400
+#define CLOCAL 0x00000800
+
+/* c_cc */
+#define VTIME  5
+#define VMIN   6
+
+#define TCSANOW                0
+#define TCSADRAIN      1
+#define TCSAFLUSH      2
+
+int tcsetattr(int fildes, int action, const struct termios *tios);
+int tcgetattr(int fildes, struct termios *tios);
+
+#endif /* _POSIX_TERMIOS_H */
diff -r 7b0c0ab0566b extras/mini-os/include/posix/time.h
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/extras/mini-os/include/posix/time.h       Mon Feb 11 17:16:12 2008 +0000
@@ -0,0 +1,10 @@
+#ifndef _POSIX_TIME_H
+#define _POSIX_TIME_H
+
+#include <sys/time.h>
+#define CLOCK_MONOTONIC        2
+#include_next <time.h>
+
+int nanosleep(const struct timespec *req, struct timespec *rem);
+
+#endif /* _POSIX_TIME_H */
diff -r 7b0c0ab0566b extras/mini-os/include/posix/unistd.h
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/extras/mini-os/include/posix/unistd.h     Mon Feb 11 17:16:12 2008 +0000
@@ -0,0 +1,11 @@
+#ifndef _POSIX_UNISTD_H
+#define _POSIX_UNISTD_H
+
+#include_next <unistd.h>
+#include <sys/select.h>
+
+#define getpagesize() PAGE_SIZE
+
+int ftruncate(int fd, off_t length);
+
+#endif /* _POSIX_UNISTD_H */
diff -r 7b0c0ab0566b extras/mini-os/include/sched.h
--- a/extras/mini-os/include/sched.h    Mon Feb 11 14:55:33 2008 +0000
+++ b/extras/mini-os/include/sched.h    Mon Feb 11 17:16:12 2008 +0000
@@ -19,6 +19,9 @@ struct thread
     struct list_head thread_list;
     u32 flags;
     s_time_t wakeup_time;
+#ifdef HAVE_LIBC
+    struct _reent reent;
+#endif
 };
 
 extern struct thread *idle_thread;
diff -r 7b0c0ab0566b extras/mini-os/include/sys/time.h
--- a/extras/mini-os/include/sys/time.h Mon Feb 11 14:55:33 2008 +0000
+++ b/extras/mini-os/include/sys/time.h Mon Feb 11 17:16:12 2008 +0000
@@ -20,6 +20,9 @@
 #ifndef _MINIOS_SYS_TIME_H_
 #define _MINIOS_SYS_TIME_H_
 
+#ifdef HAVE_LIBC
+#include_next <sys/time.h>
+#else
 struct timespec {
     time_t      tv_sec;
     long        tv_nsec;
@@ -34,5 +37,6 @@ struct timeval {
 };
 
 int      gettimeofday(struct timeval *tv, void *tz);
+#endif
 
 #endif /* _MINIOS_SYS_TIME_H_ */
diff -r 7b0c0ab0566b extras/mini-os/include/time.h
--- a/extras/mini-os/include/time.h     Mon Feb 11 14:55:33 2008 +0000
+++ b/extras/mini-os/include/time.h     Mon Feb 11 17:16:12 2008 +0000
@@ -17,8 +17,9 @@
  ****************************************************************************
  */
 
-#ifndef _TIME_H_
-#define _TIME_H_
+#ifndef _MINIOS_TIME_H_
+#define _MINIOS_TIME_H_
+#include <types.h>
 
 /*
  * System Time
@@ -44,8 +45,12 @@ typedef s64 s_time_t;
 /* wall clock time  */
 typedef long time_t;
 typedef long suseconds_t;
+
 #include <sys/time.h>
 
+#ifdef HAVE_LIBC
+#include_next <time.h>
+#endif
 
 /* prototypes */
 void     init_time(void);
@@ -54,4 +59,4 @@ u64      monotonic_clock(void);
 u64      monotonic_clock(void);
 void     block_domain(s_time_t until);
 
-#endif /* _TIME_H_ */
+#endif /* _MINIOS_TIME_H_ */
diff -r 7b0c0ab0566b extras/mini-os/include/x86/arch_mm.h
--- a/extras/mini-os/include/x86/arch_mm.h      Mon Feb 11 14:55:33 2008 +0000
+++ b/extras/mini-os/include/x86/arch_mm.h      Mon Feb 11 17:16:12 2008 +0000
@@ -177,7 +177,7 @@ typedef unsigned long pgentry_t;
 /* to align the pointer to the (next) page boundary */
 #define PAGE_ALIGN(addr)        (((addr)+PAGE_SIZE-1)&PAGE_MASK)
 
-#define STACK_SIZE_PAGE_ORDER  1
+#define STACK_SIZE_PAGE_ORDER  4
 #define STACK_SIZE             (PAGE_SIZE * (1 << STACK_SIZE_PAGE_ORDER))
 
 #ifndef __ASSEMBLY__
@@ -257,5 +257,11 @@ static __inline__ paddr_t machine_to_phy
 
 #define map_frames(f, n) map_frames_ex(f, n, 1, 0, 1, DOMID_SELF, 0, L1_PROT)
 #define map_zero(n, a) map_frames_ex(&mfn_zero, n, 0, 0, a, DOMID_SELF, 0, 
L1_PROT_RO)
+#ifndef __ASSEMBLY__
+void do_map_frames(unsigned long addr,
+        unsigned long *f, unsigned long n, unsigned long stride,
+       unsigned long increment, domid_t id, int may_fail, unsigned long prot);
+#endif
+#define do_map_zero(start, n) do_map_frames(start, &mfn_zero, n, 0, 0, 
DOMID_SELF, 0, L1_PROT_RO)
 
 #endif /* _ARCH_MM_H_ */
diff -r 7b0c0ab0566b extras/mini-os/include/x86/arch_spinlock.h
--- a/extras/mini-os/include/x86/arch_spinlock.h        Mon Feb 11 14:55:33 
2008 +0000
+++ b/extras/mini-os/include/x86/arch_spinlock.h        Mon Feb 11 17:16:12 
2008 +0000
@@ -4,6 +4,7 @@
 #define __ARCH_ASM_SPINLOCK_H
 
 #include <lib.h>
+#include "os.h"
 
 
 #define ARCH_SPIN_LOCK_UNLOCKED (spinlock_t) { 1 }
diff -r 7b0c0ab0566b extras/mini-os/include/x86/os.h
--- a/extras/mini-os/include/x86/os.h   Mon Feb 11 14:55:33 2008 +0000
+++ b/extras/mini-os/include/x86/os.h   Mon Feb 11 17:16:12 2008 +0000
@@ -139,6 +139,8 @@ do {                                                        
                \
 /* This is a barrier for the compiler only, NOT the processor! */
 #define barrier() __asm__ __volatile__("": : :"memory")
 
+#ifndef __barriers_defined
+#define __barriers_defined
 #if defined(__i386__)
 #define mb()    __asm__ __volatile__ ("lock; addl $0,0(%%esp)": : :"memory")
 #define rmb()   __asm__ __volatile__ ("lock; addl $0,0(%%esp)": : :"memory")
@@ -147,6 +149,7 @@ do {                                                        
                \
 #define mb()    __asm__ __volatile__ ("mfence":::"memory")
 #define rmb()   __asm__ __volatile__ ("lfence":::"memory")
 #define wmb()  __asm__ __volatile__ ("sfence" ::: "memory") /* From 
CONFIG_UNORDERED_IO (linux) */
+#endif
 #endif
 
 
@@ -563,6 +566,7 @@ static __inline__ int synch_var_test_bit
  synch_var_test_bit((nr),(addr)))
 
 
+#undef ADDR
 
 #endif /* not assembly */
 #endif /* _OS_H_ */
diff -r 7b0c0ab0566b extras/mini-os/include/xs.h
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/extras/mini-os/include/xs.h       Mon Feb 11 17:16:12 2008 +0000
@@ -0,0 +1,168 @@
+/* 
+    Xen Store Daemon providing simple tree-like database.
+    Copyright (C) 2005 Rusty Russell IBM Corporation
+
+    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.1 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#ifndef _XS_H
+#define _XS_H
+
+#include <xs_lib.h>
+
+#define XBT_NULL 0
+
+struct xs_handle;
+typedef uint32_t xs_transaction_t;
+
+/* On failure, these routines set errno. */
+
+/* Connect to the xs daemon.
+ * Returns a handle or NULL.
+ */
+struct xs_handle *xs_daemon_open(void);
+struct xs_handle *xs_domain_open(void);
+
+/* Connect to the xs daemon (readonly for non-root clients).
+ * Returns a handle or NULL.
+ */
+struct xs_handle *xs_daemon_open_readonly(void);
+
+/* Close the connection to the xs daemon. */
+void xs_daemon_close(struct xs_handle *);
+
+/* Get contents of a directory.
+ * Returns a malloced array: call free() on it after use.
+ * Num indicates size.
+ */
+char **xs_directory(struct xs_handle *h, xs_transaction_t t,
+                   const char *path, unsigned int *num);
+
+/* Get the value of a single file, nul terminated.
+ * Returns a malloced value: call free() on it after use.
+ * len indicates length in bytes, not including terminator.
+ */
+void *xs_read(struct xs_handle *h, xs_transaction_t t,
+             const char *path, unsigned int *len);
+
+/* Write the value of a single file.
+ * Returns false on failure.
+ */
+bool xs_write(struct xs_handle *h, xs_transaction_t t,
+             const char *path, const void *data, unsigned int len);
+
+/* Create a new directory.
+ * Returns false on failure, or success if it already exists.
+ */
+bool xs_mkdir(struct xs_handle *h, xs_transaction_t t,
+             const char *path);
+
+/* Destroy a file or directory (and children).
+ * Returns false on failure, or if it doesn't exist.
+ */
+bool xs_rm(struct xs_handle *h, xs_transaction_t t,
+          const char *path);
+
+/* Get permissions of node (first element is owner, first perms is "other").
+ * Returns malloced array, or NULL: call free() after use.
+ */
+struct xs_permissions *xs_get_permissions(struct xs_handle *h,
+                                         xs_transaction_t t,
+                                         const char *path, unsigned int *num);
+
+/* Set permissions of node (must be owner).
+ * Returns false on failure.
+ */
+bool xs_set_permissions(struct xs_handle *h, xs_transaction_t t,
+                       const char *path, struct xs_permissions *perms,
+                       unsigned int num_perms);
+
+/* Watch a node for changes (poll on fd to detect, or call read_watch()).
+ * When the node (or any child) changes, fd will become readable.
+ * Token is returned when watch is read, to allow matching.
+ * Returns false on failure.
+ */
+bool xs_watch(struct xs_handle *h, const char *path, const char *token);
+
+/* Return the FD to poll on to see if a watch has fired. */
+int xs_fileno(struct xs_handle *h);
+
+/* Find out what node change was on (will block if nothing pending).
+ * Returns array containing the path and token. Use XS_WATCH_* to access these
+ * elements. Call free() after use.
+ */
+char **xs_read_watch(struct xs_handle *h, unsigned int *num);
+
+/* Remove a watch on a node: implicitly acks any outstanding watch.
+ * Returns false on failure (no watch on that node).
+ */
+bool xs_unwatch(struct xs_handle *h, const char *path, const char *token);
+
+/* Start a transaction: changes by others will not be seen during this
+ * transaction, and changes will not be visible to others until end.
+ * You can only have one transaction at any time.
+ * Returns NULL on failure.
+ */
+xs_transaction_t xs_transaction_start(struct xs_handle *h);
+
+/* End a transaction.
+ * If abandon is true, transaction is discarded instead of committed.
+ * Returns false on failure: if errno == EAGAIN, you have to restart
+ * transaction.
+ */
+bool xs_transaction_end(struct xs_handle *h, xs_transaction_t t,
+                       bool abort);
+
+/* Introduce a new domain.
+ * This tells the store daemon about a shared memory page, event channel and
+ * store path associated with a domain: the domain uses these to communicate.
+ */
+bool xs_introduce_domain(struct xs_handle *h,
+                        unsigned int domid,
+                        unsigned long mfn,
+                         unsigned int eventchn); 
+/* Resume a domain.
+ * Clear the shutdown flag for this domain in the store.
+ */
+bool xs_resume_domain(struct xs_handle *h, unsigned int domid);
+
+/* Release a domain.
+ * Tells the store domain to release the memory page to the domain.
+ */
+bool xs_release_domain(struct xs_handle *h, unsigned int domid);
+
+/* Query the home path of a domain.  Call free() after use.
+ */
+char *xs_get_domain_path(struct xs_handle *h, unsigned int domid);
+
+/* Return whether the domain specified has been introduced to xenstored.
+ */
+bool xs_is_domain_introduced(struct xs_handle *h, unsigned int domid);
+
+/* Only useful for DEBUG versions */
+char *xs_debug_command(struct xs_handle *h, const char *cmd,
+                      void *data, unsigned int len);
+
+#endif /* _XS_H */
+
+/*
+ * Local variables:
+ *  c-file-style: "linux"
+ *  indent-tabs-mode: t
+ *  c-indent-level: 8
+ *  c-basic-offset: 8
+ *  tab-width: 8
+ * End:
+ */
diff -r 7b0c0ab0566b extras/mini-os/include/xs_lib.h
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/extras/mini-os/include/xs_lib.h   Mon Feb 11 17:16:12 2008 +0000
@@ -0,0 +1,69 @@
+/* 
+    Common routines between Xen store user library and daemon.
+    Copyright (C) 2005 Rusty Russell IBM Corporation
+
+    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.1 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#ifndef _XS_LIB_H
+#define _XS_LIB_H
+
+#include <stdbool.h>
+#include <limits.h>
+#include <errno.h>
+#include <stdint.h>
+#include <xen/io/xs_wire.h>
+
+/* Bitmask of permissions. */
+enum xs_perm_type {
+       XS_PERM_NONE = 0,
+       XS_PERM_READ = 1,
+       XS_PERM_WRITE = 2,
+       /* Internal use. */
+       XS_PERM_ENOENT_OK = 4,
+       XS_PERM_OWNER = 8,
+};
+
+struct xs_permissions
+{
+       unsigned int id;
+       enum xs_perm_type perms;
+};
+
+/* Each 10 bits takes ~ 3 digits, plus one, plus one for nul terminator. */
+#define MAX_STRLEN(x) ((sizeof(x) * CHAR_BIT + CHAR_BIT-1) / 10 * 3 + 2)
+
+/* Path for various daemon things: env vars can override. */
+const char *xs_daemon_rootdir(void);
+const char *xs_daemon_rundir(void);
+const char *xs_daemon_socket(void);
+const char *xs_daemon_socket_ro(void);
+const char *xs_domain_dev(void);
+const char *xs_daemon_tdb(void);
+
+/* Simple write function: loops for you. */
+bool xs_write_all(int fd, const void *data, unsigned int len);
+
+/* Convert strings to permissions.  False if a problem. */
+bool xs_strings_to_perms(struct xs_permissions *perms, unsigned int num,
+                        const char *strings);
+
+/* Convert permissions to a string (up to len MAX_STRLEN(unsigned int)+1). */
+bool xs_perm_to_string(const struct xs_permissions *perm, char *buffer);
+
+/* Given a string and a length, count how many strings (nul terms). */
+unsigned int xs_count_strings(const char *strings, unsigned int len);
+
+#endif /* _XS_LIB_H */
diff -r 7b0c0ab0566b extras/mini-os/lib/sys.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/extras/mini-os/lib/sys.c  Mon Feb 11 17:16:12 2008 +0000
@@ -0,0 +1,1083 @@
+/*
+ * POSIX-compatible libc layer
+ *
+ * Samuel Thibault <Samuel.Thibault@xxxxxxxxxxxxx>, October 2007
+ *
+ * Provides the UNIXish part of the standard libc function.
+ *
+ * Relatively straight-forward: just multiplex the file descriptor operations
+ * among the various file types (console, FS, network, ...)
+ */
+
+//#define LIBC_VERBOSE
+//#define LIBC_DEBUG
+
+#ifdef LIBC_DEBUG
+#define DEBUG(fmt,...) printk(fmt, ##__VA_ARGS__)
+#else
+#define DEBUG(fmt,...)
+#endif
+
+#ifdef HAVE_LIBC
+#include <os.h>
+#include <console.h>
+#include <sched.h>
+#include <events.h>
+#include <wait.h>
+#include <netfront.h>
+#include <blkfront.h>
+#include <xenbus.h>
+#include <xs.h>
+
+#include <sys/types.h>
+#include <sys/unistd.h>
+#include <sys/stat.h>
+#include <sys/mman.h>
+#include <time.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <pthread.h>
+#include <assert.h>
+#include <dirent.h>
+#include <stdlib.h>
+#include <math.h>
+
+#include <lwip/sockets.h>
+#include <fs.h>
+
+#define debug(fmt, ...) \
+
+#define print_unsupported(fmt, ...) \
+    printk("Unsupported function "fmt" called in Mini-OS kernel\n", ## 
__VA_ARGS__);
+
+/* Crash on function call */
+#define unsupported_function_crash(function) \
+    int __unsup_##function(void) asm(#function); \
+    int __unsup_##function(void) \
+    { \
+       print_unsupported(#function); \
+       do_exit(); \
+    }
+
+/* Log and err out on function call */
+#define unsupported_function_log(type, function, ret) \
+    type __unsup_##function(void) asm(#function); \
+    type __unsup_##function(void) \
+    { \
+       print_unsupported(#function); \
+       errno = ENOSYS; \
+       return ret; \
+    }
+
+/* Err out on function call */
+#define unsupported_function(type, function, ret) \
+    type __unsup_##function(void) asm(#function); \
+    type __unsup_##function(void) \
+    { \
+       errno = ENOSYS; \
+       return ret; \
+    }
+
+#define NOFILE 32
+extern int xc_evtchn_close(int fd);
+
+pthread_mutex_t fd_lock = PTHREAD_MUTEX_INITIALIZER;
+struct file files[NOFILE] = {
+    { .type = FTYPE_CONSOLE }, /* stdin */
+    { .type = FTYPE_CONSOLE }, /* stdout */
+    { .type = FTYPE_CONSOLE }, /* stderr */
+};
+
+DECLARE_WAIT_QUEUE_HEAD(event_queue);
+
+int alloc_fd(enum fd_type type)
+{
+    int i;
+    pthread_mutex_lock(&fd_lock);
+    for (i=0; i<NOFILE; i++) {
+       if (files[i].type == FTYPE_NONE) {
+           files[i].type = type;
+           pthread_mutex_unlock(&fd_lock);
+           return i;
+       }
+    }
+    pthread_mutex_unlock(&fd_lock);
+    printk("Too many opened files\n");
+    do_exit();
+}
+
+void close_all_files(void)
+{
+    int i;
+    pthread_mutex_lock(&fd_lock);
+    for (i=NOFILE - 1; i > 0; i--)
+       if (files[i].type != FTYPE_NONE)
+            close(i);
+    pthread_mutex_unlock(&fd_lock);
+}
+
+int dup2(int oldfd, int newfd)
+{
+    pthread_mutex_lock(&fd_lock);
+    if (files[newfd].type != FTYPE_NONE)
+       close(newfd);
+    // XXX: this is a bit bogus, as we are supposed to share the offset etc
+    files[newfd] = files[oldfd];
+    pthread_mutex_unlock(&fd_lock);
+    return 0;
+}
+
+pid_t getpid(void)
+{
+    return 1;
+}
+
+pid_t getppid(void)
+{
+    return 1;
+}
+
+pid_t setsid(void)
+{
+    return 1;
+}
+
+char *getcwd(char *buf, size_t size)
+{
+    snprintf(buf, size, "/");
+    return buf;
+}
+
+#define LOG_PATH "/var/log/"
+
+int mkdir(const char *pathname, mode_t mode)
+{
+    int ret;
+    ret = fs_create(fs_import, (char *) pathname, 1, mode);
+    if (ret < 0) {
+        errno = EIO;
+        return -1;
+    }
+    return 0;
+}
+
+int open(const char *pathname, int flags, ...)
+{
+    int fs_fd, fd;
+    /* Ugly, but fine.  */
+    if (!strncmp(pathname,LOG_PATH,strlen(LOG_PATH))) {
+       fd = alloc_fd(FTYPE_CONSOLE);
+        printk("open(%s) -> %d\n", pathname, fd);
+        return fd;
+    }
+    printk("open(%s)", pathname);
+    fs_fd = fs_open(fs_import, (void *) pathname);
+    if (fs_fd < 0) {
+       errno = EIO;
+       return -1;
+    }
+    fd = alloc_fd(FTYPE_FILE);
+    printk("-> %d\n", fd);
+    files[fd].file.fd = fs_fd;
+    files[fd].file.offset = 0;
+    return fd;
+}
+#if defined(__x86_64__) || defined(__ia64__)
+__typeof__(open) open64 __attribute__((__alias__("open")));
+#endif
+
+int isatty(int fd)
+{
+    return files[fd].type == FTYPE_CONSOLE;
+}
+
+int read(int fd, void *buf, size_t nbytes)
+{
+    switch (files[fd].type) {
+       case FTYPE_CONSOLE:
+           return 0;
+       case FTYPE_FILE: {
+           ssize_t ret;
+           if (nbytes > PAGE_SIZE)
+               nbytes = PAGE_SIZE;
+           ret = fs_read(fs_import, files[fd].file.fd, buf, nbytes, 
files[fd].file.offset);
+           if (ret > 0) {
+               files[fd].file.offset += ret;
+               return ret;
+           } else if (ret < 0) {
+               errno = EIO;
+               return -1;
+           }
+           return 0;
+       }
+       case FTYPE_SOCKET:
+           return lwip_read(files[fd].socket.fd, buf, nbytes);
+       case FTYPE_TAP: {
+           ssize_t ret;
+           ret = netfront_receive(files[fd].tap.dev, buf, nbytes);
+           if (ret <= 0) {
+               errno = EAGAIN;
+               return -1;
+           }
+           return ret;
+       }
+       case FTYPE_NONE:
+       case FTYPE_XENBUS:
+       case FTYPE_EVTCHN:
+       case FTYPE_BLK:
+           break;
+    }
+    printk("read(%d): Bad descriptor\n", fd);
+    errno = EBADF;
+    return -1;
+}
+
+int write(int fd, const void *buf, size_t nbytes)
+{
+    switch (files[fd].type) {
+       case FTYPE_CONSOLE:
+           console_print((char *)buf, nbytes);
+           return nbytes;
+       case FTYPE_FILE: {
+           ssize_t ret;
+           if (nbytes > PAGE_SIZE)
+               nbytes = PAGE_SIZE;
+           ret = fs_write(fs_import, files[fd].file.fd, (void *) buf, nbytes, 
files[fd].file.offset);
+           if (ret > 0) {
+               files[fd].file.offset += ret;
+               return ret;
+           } else if (ret < 0) {
+               errno = EIO;
+               return -1;
+           }
+           return 0;
+       }
+       case FTYPE_SOCKET:
+           return lwip_write(files[fd].socket.fd, (void*) buf, nbytes);
+       case FTYPE_TAP:
+           netfront_xmit(files[fd].tap.dev, (void*) buf, nbytes);
+           return nbytes;
+       case FTYPE_NONE:
+       case FTYPE_XENBUS:
+       case FTYPE_EVTCHN:
+       case FTYPE_BLK:
+           break;
+    }
+    printk("write(%d): Bad descriptor\n", fd);
+    errno = EBADF;
+    return -1;
+}
+
+off_t lseek(int fd, off_t offset, int whence)
+{
+    if (files[fd].type != FTYPE_FILE) {
+       errno = ESPIPE;
+       return (off_t) -1;
+    }
+    switch (whence) {
+       case SEEK_SET:
+           files[fd].file.offset = offset;
+           break;
+       case SEEK_CUR:
+           files[fd].file.offset += offset;
+           break;
+       case SEEK_END: {
+           struct stat st;
+           int ret;
+           ret = fstat(fd, &st);
+           if (ret)
+               return -1;
+           files[fd].file.offset = st.st_size + offset;
+           break;
+       }
+       default:
+           errno = EINVAL;
+           return -1;
+    }
+    return files[fd].file.offset;
+}
+#if defined(__x86_64__) || defined(__ia64__)
+__typeof__(lseek) lseek64 __attribute__((__alias__("lseek")));
+#endif
+
+int fsync(int fd) {
+    switch (files[fd].type) {
+       case FTYPE_FILE: {
+           int ret;
+           ret = fs_sync(fs_import, files[fd].file.fd);
+           if (ret < 0) {
+               errno = EIO;
+               return -1;
+           }
+           return 0;
+       }
+       case FTYPE_NONE:
+       case FTYPE_CONSOLE:
+       case FTYPE_SOCKET:
+       case FTYPE_XENBUS:
+       case FTYPE_EVTCHN:
+       case FTYPE_TAP:
+       case FTYPE_BLK:
+           break;
+    }
+    printk("fsync(%d): Bad descriptor\n", fd);
+    errno = EBADF;
+    return -1;
+}
+
+int close(int fd)
+{
+    printk("close(%d)\n", fd);
+    switch (files[fd].type) {
+       case FTYPE_CONSOLE:
+           files[fd].type = FTYPE_NONE;
+           return 0;
+       case FTYPE_FILE: {
+           int ret = fs_close(fs_import, files[fd].file.fd);
+           files[fd].type = FTYPE_NONE;
+           if (ret < 0) {
+               errno = EIO;
+               return -1;
+           }
+           return 0;
+       }
+       case FTYPE_XENBUS:
+            xs_daemon_close((void*)(intptr_t) fd);
+            return 0;
+       case FTYPE_SOCKET: {
+           int res = lwip_close(files[fd].socket.fd);
+           files[fd].type = FTYPE_NONE;
+           return res;
+       }
+       case FTYPE_EVTCHN:
+            xc_evtchn_close(fd);
+            return 0;
+       case FTYPE_TAP:
+           shutdown_netfront(files[fd].tap.dev);
+           files[fd].type = FTYPE_NONE;
+           return 0;
+       case FTYPE_BLK:
+            shutdown_blkfront(files[fd].blk.dev);
+           files[fd].type = FTYPE_NONE;
+           return 0;
+       case FTYPE_NONE:
+           break;
+    }
+    printk("close(%d): Bad descriptor\n", fd);
+    errno = EBADF;
+    return -1;
+}
+
+static void init_stat(struct stat *buf)
+{
+    memset(buf, 0, sizeof(*buf));
+    buf->st_dev = 0;
+    buf->st_ino = 0;
+    buf->st_nlink = 1;
+    buf->st_rdev = 0;
+    buf->st_blksize = 4096;
+    buf->st_blocks = 0;
+}
+
+static void stat_from_fs(struct stat *buf, struct fsif_stat_response *stat)
+{
+    buf->st_mode = stat->stat_mode;
+    buf->st_uid = stat->stat_uid;
+    buf->st_gid = stat->stat_gid;
+    buf->st_size = stat->stat_size;
+    buf->st_atime = stat->stat_atime;
+    buf->st_mtime = stat->stat_mtime;
+    buf->st_ctime = stat->stat_ctime;
+}
+
+int stat(const char *path, struct stat *buf)
+{
+    struct fsif_stat_response stat;
+    int ret;
+    int fs_fd;
+    printk("stat(%s)\n", path);
+    fs_fd = fs_open(fs_import, (char*) path);
+    if (fs_fd < 0) {
+       errno = EIO;
+       ret = -1;
+       goto out;
+    }
+    ret = fs_stat(fs_import, fs_fd, &stat);
+    if (ret < 0) {
+       errno = EIO;
+       ret = -1;
+       goto outfd;
+    }
+    init_stat(buf);
+    stat_from_fs(buf, &stat);
+    ret = 0;
+
+outfd:
+    fs_close(fs_import, fs_fd);
+out:
+    return ret;
+}
+
+int fstat(int fd, struct stat *buf)
+{
+    init_stat(buf);
+    switch (files[fd].type) {
+       case FTYPE_CONSOLE:
+       case FTYPE_SOCKET: {
+           buf->st_mode = (files[fd].type == FTYPE_CONSOLE?S_IFCHR:S_IFSOCK) | 
S_IRUSR|S_IWUSR;
+           buf->st_uid = 0;
+           buf->st_gid = 0;
+           buf->st_size = 0;
+           buf->st_atime = 
+           buf->st_mtime = 
+           buf->st_ctime = time(NULL);
+           return 0;
+       }
+       case FTYPE_FILE: {
+           struct fsif_stat_response stat;
+           int ret;
+           ret = fs_stat(fs_import, files[fd].file.fd, &stat);
+           if (ret < 0) {
+               errno = EIO;
+               return -1;
+           }
+           /* The protocol is a bit evasive about this value */
+           stat_from_fs(buf, &stat);
+           return 0;
+       }
+       case FTYPE_NONE:
+       case FTYPE_XENBUS:
+       case FTYPE_EVTCHN:
+       case FTYPE_TAP:
+       case FTYPE_BLK:
+           break;
+    }
+
+    printk("statf(%d): Bad descriptor\n", fd);
+    errno = EBADF;
+    return -1;
+}
+
+int ftruncate(int fd, off_t length)
+{
+    switch (files[fd].type) {
+       case FTYPE_FILE: {
+            int ret;
+            ret = fs_truncate(fs_import, files[fd].file.fd, length);
+           if (ret < 0) {
+               errno = EIO;
+               return -1;
+           }
+           return 0;
+       }
+       case FTYPE_NONE:
+       case FTYPE_CONSOLE:
+       case FTYPE_SOCKET:
+       case FTYPE_XENBUS:
+       case FTYPE_EVTCHN:
+       case FTYPE_TAP:
+       case FTYPE_BLK:
+           break;
+    }
+
+    printk("ftruncate(%d): Bad descriptor\n", fd);
+    errno = EBADF;
+    return -1;
+}
+
+int remove(const char *pathname)
+{
+    int ret;
+    printk("remove(%s)", pathname);
+    ret = fs_remove(fs_import, (char*) pathname);
+    if (ret < 0) {
+        errno = EIO;
+        return -1;
+    }
+    return 0;
+}
+
+int unlink(const char *pathname)
+{
+    return remove(pathname);
+}
+
+int rmdir(const char *pathname)
+{
+    return remove(pathname);
+}
+
+int fcntl(int fd, int cmd, ...)
+{
+    long arg;
+    va_list ap;
+    va_start(ap, cmd);
+    arg = va_arg(ap, long);
+    va_end(ap);
+
+    switch (cmd) {
+       case F_SETFL:
+           if (files[fd].type == FTYPE_SOCKET && !(arg & ~O_NONBLOCK)) {
+               /* Only flag supported: non-blocking mode */
+               uint32_t nblock = !!(arg & O_NONBLOCK);
+               return lwip_ioctl(files[fd].socket.fd, FIONBIO, &nblock);
+           }
+           /* Fallthrough */
+       default:
+           printk("fcntl(%d, %d, %lx/%lo)\n", fd, cmd, arg, arg);
+           errno = ENOSYS;
+           return -1;
+    }
+}
+
+DIR *opendir(const char *name)
+{
+    DIR *ret;
+    ret = malloc(sizeof(*ret));
+    ret->name = strdup(name);
+    ret->offset = 0;
+    ret->entries = NULL;
+    ret->curentry = -1;
+    ret->nbentries = 0;
+    ret->has_more = 1;
+    return ret;
+}
+
+struct dirent *readdir(DIR *dir)
+{
+    if (dir->curentry >= 0) {
+        free(dir->entries[dir->curentry]);
+        dir->entries[dir->curentry] = NULL;
+    }
+    dir->curentry++;
+    if (dir->curentry >= dir->nbentries) {
+        dir->offset += dir->nbentries;
+        free(dir->entries);
+        dir->curentry = -1;
+        dir->nbentries = 0;
+        if (!dir->has_more)
+            return NULL;
+        dir->entries = fs_list(fs_import, dir->name, dir->offset, 
&dir->nbentries, &dir->has_more);
+        if (!dir->entries || !dir->nbentries)
+            return NULL;
+        dir->curentry = 0;
+    }
+    dir->dirent.d_name = dir->entries[dir->curentry];
+    return &dir->dirent;
+} 
+int closedir(DIR *dir)
+{
+    int i;
+    for (i=0; i<dir->nbentries; i++)
+        free(dir->entries[i]);
+    free(dir->entries);
+    free(dir->name);
+    free(dir);
+    return 0;
+}
+
+/* We assume that only the main thread calls select(). */
+
+static const char file_types[] = {
+    [FTYPE_NONE]       = 'N',
+    [FTYPE_CONSOLE]    = 'C',
+    [FTYPE_FILE]       = 'F',
+    [FTYPE_XENBUS]     = 'X',
+    [FTYPE_EVTCHN]     = 'E',
+    [FTYPE_SOCKET]     = 'S',
+    [FTYPE_TAP]                = 'T',
+    [FTYPE_BLK]                = 'B',
+};
+#ifdef LIBC_DEBUG
+static void dump_set(int nfds, fd_set *readfds, fd_set *writefds, fd_set 
*exceptfds, struct timeval *timeout)
+{
+    int i, comma;
+#define printfds(set) do {\
+    comma = 0; \
+    for (i = 0; i < nfds; i++) { \
+       if (FD_ISSET(i, set)) { \
+           if (comma) \
+               printk(", "); \
+           printk("%d(%c)", i, file_types[files[i].type]); \
+           comma = 1; \
+       } \
+    } \
+} while (0)
+
+    printk("[");
+    if (readfds)
+       printfds(readfds);
+    printk("], [");
+    if (writefds)
+       printfds(writefds);
+    printk("], [");
+    if (exceptfds)
+       printfds(exceptfds);
+    printk("], ");
+    if (timeout)
+       printk("{ %ld, %ld }", timeout->tv_sec, timeout->tv_usec);
+}
+#else
+#define dump_set(nfds, readfds, writefds, exceptfds, timeout)
+#endif
+
+/* Just poll without blocking */
+static int select_poll(int nfds, fd_set *readfds, fd_set *writefds, fd_set 
*exceptfds)
+{
+    int i, n = 0, sock_n, sock_nfds = 0;
+    fd_set sock_readfds, sock_writefds, sock_exceptfds;
+    struct timeval timeout = { .tv_sec = 0, .tv_usec = 0};
+
+#ifdef LIBC_VERBOSE
+    static int nb;
+    static int nbread[NOFILE], nbwrite[NOFILE], nbexcept[NOFILE];
+    static s64_t lastshown;
+
+    nb++;
+#endif
+
+    /* first poll network */
+    FD_ZERO(&sock_readfds);
+    FD_ZERO(&sock_writefds);
+    FD_ZERO(&sock_exceptfds);
+    for (i = 0; i < nfds; i++) {
+       if (files[i].type == FTYPE_SOCKET) {
+           if (FD_ISSET(i, readfds)) {
+               FD_SET(files[i].socket.fd, &sock_readfds);
+               sock_nfds = i+1;
+           }
+           if (FD_ISSET(i, writefds)) {
+               FD_SET(files[i].socket.fd, &sock_writefds);
+               sock_nfds = i+1;
+           }
+           if (FD_ISSET(i, exceptfds)) {
+               FD_SET(files[i].socket.fd, &sock_exceptfds);
+               sock_nfds = i+1;
+           }
+       }
+    }
+    DEBUG("lwip_select(");
+    dump_set(nfds, &sock_readfds, &sock_writefds, &sock_exceptfds, &timeout);
+    DEBUG("); -> ");
+    sock_n = lwip_select(sock_nfds, &sock_readfds, &sock_writefds, 
&sock_exceptfds, &timeout);
+    dump_set(nfds, &sock_readfds, &sock_writefds, &sock_exceptfds, &timeout);
+    DEBUG("\n");
+
+    /* Then see others as well. */
+    for (i = 0; i < nfds; i++) {
+       switch(files[i].type) {
+       case FTYPE_NONE:
+           if (FD_ISSET(i, readfds) || FD_ISSET(i, writefds) || FD_ISSET(i, 
exceptfds))
+               printk("bogus fd %d in select\n", i);
+           /* Fallthrough.  */
+       case FTYPE_FILE:
+           FD_CLR(i, readfds);
+           FD_CLR(i, writefds);
+           FD_CLR(i, exceptfds);
+           break;
+       case FTYPE_CONSOLE:
+           FD_CLR(i, readfds);
+           if (FD_ISSET(i, writefds))
+                n++;
+           FD_CLR(i, exceptfds);
+           break;
+       case FTYPE_XENBUS:
+           if (FD_ISSET(i, readfds)) {
+                if (files[i].xenbus.events)
+                   n++;
+               else
+                   FD_CLR(i, readfds);
+           }
+           FD_CLR(i, writefds);
+           FD_CLR(i, exceptfds);
+           break;
+       case FTYPE_EVTCHN:
+       case FTYPE_TAP:
+       case FTYPE_BLK:
+           if (FD_ISSET(i, readfds)) {
+               if (files[i].read)
+                   n++;
+               else
+                   FD_CLR(i, readfds);
+           }
+           FD_CLR(i, writefds);
+           FD_CLR(i, exceptfds);
+           break;
+       case FTYPE_SOCKET:
+           if (FD_ISSET(i, readfds)) {
+               /* Optimize no-network-packet case.  */
+               if (sock_n && FD_ISSET(files[i].socket.fd, &sock_readfds))
+                   n++;
+               else
+                   FD_CLR(i, readfds);
+           }
+            if (FD_ISSET(i, writefds)) {
+               if (sock_n && FD_ISSET(files[i].socket.fd, &sock_writefds))
+                   n++;
+               else
+                   FD_CLR(i, writefds);
+            }
+            if (FD_ISSET(i, exceptfds)) {
+               if (sock_n && FD_ISSET(files[i].socket.fd, &sock_exceptfds))
+                   n++;
+               else
+                   FD_CLR(i, exceptfds);
+            }
+           break;
+       }
+#ifdef LIBC_VERBOSE
+       if (FD_ISSET(i, readfds))
+           nbread[i]++;
+       if (FD_ISSET(i, writefds))
+           nbwrite[i]++;
+       if (FD_ISSET(i, exceptfds))
+           nbexcept[i]++;
+#endif
+    }
+#ifdef LIBC_VERBOSE
+    if (NOW() > lastshown + 1000000000ull) {
+       lastshown = NOW();
+       printk("%lu MB free, ", num_free_pages() / ((1 << 20) / PAGE_SIZE));
+       printk("%d(%d): ", nb, sock_n);
+       for (i = 0; i < nfds; i++) {
+           if (nbread[i] || nbwrite[i] || nbexcept[i])
+               printk(" %d(%c):", i, file_types[files[i].type]);
+           if (nbread[i])
+               printk(" %dR", nbread[i]);
+           if (nbwrite[i])
+               printk(" %dW", nbwrite[i]);
+           if (nbexcept[i])
+               printk(" %dE", nbexcept[i]);
+       }
+       printk("\n");
+       memset(nbread, 0, sizeof(nbread));
+       memset(nbwrite, 0, sizeof(nbwrite));
+       memset(nbexcept, 0, sizeof(nbexcept));
+       nb = 0;
+    }
+#endif
+    return n;
+}
+
+/* The strategy is to
+ * - announce that we will maybe sleep
+ * - poll a bit ; if successful, return
+ * - if timeout, return
+ * - really sleep (except if somebody woke us in the meanwhile) */
+int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
+       struct timeval *timeout)
+{
+    int n, ret;
+    fd_set myread, mywrite, myexcept;
+    struct thread *thread = get_current();
+    s_time_t start = NOW(), stop;
+    DEFINE_WAIT(w1);
+    DEFINE_WAIT(w2);
+    DEFINE_WAIT(w3);
+    DEFINE_WAIT(w4);
+
+    assert(thread == main_thread);
+
+    DEBUG("select(%d, ", nfds);
+    dump_set(nfds, readfds, writefds, exceptfds, timeout);
+    DEBUG(");\n");
+
+    if (timeout)
+       stop = start + SECONDS(timeout->tv_sec) + timeout->tv_usec * 1000;
+    else
+       /* just make gcc happy */
+       stop = start;
+
+    /* Tell people we're going to sleep before looking at what they are
+     * saying, hence letting them wake us if events happen between here and
+     * schedule() */
+    add_waiter(w1, netfront_queue);
+    add_waiter(w2, event_queue);
+    add_waiter(w3, blkfront_queue);
+    add_waiter(w4, xenbus_watch_queue);
+
+    myread = *readfds;
+    mywrite = *writefds;
+    myexcept = *exceptfds;
+    DEBUG("polling ");
+    dump_set(nfds, &myread, &mywrite, &myexcept, timeout);
+    DEBUG("\n");
+    n = select_poll(nfds, &myread, &mywrite, &myexcept);
+
+    if (n) {
+       dump_set(nfds, readfds, writefds, exceptfds, timeout);
+       if (readfds)
+           *readfds = myread;
+       if (writefds)
+           *writefds = mywrite;
+       if (exceptfds)
+           *exceptfds = myexcept;
+       DEBUG(" -> ");
+       dump_set(nfds, readfds, writefds, exceptfds, timeout);
+       DEBUG("\n");
+       wake(thread);
+       ret = n;
+       goto out;
+    }
+    if (timeout && NOW() >= stop) {
+       if (readfds)
+           FD_ZERO(readfds);
+       if (writefds)
+           FD_ZERO(writefds);
+       if (exceptfds)
+           FD_ZERO(exceptfds);
+       timeout->tv_sec = 0;
+       timeout->tv_usec = 0;
+       wake(thread);
+       ret = 0;
+       goto out;
+    }
+
+    if (timeout)
+       thread->wakeup_time = stop;
+    schedule();
+
+    myread = *readfds;
+    mywrite = *writefds;
+    myexcept = *exceptfds;
+    n = select_poll(nfds, &myread, &mywrite, &myexcept);
+
+    if (n) {
+       if (readfds)
+           *readfds = myread;
+       if (writefds)
+           *writefds = mywrite;
+       if (exceptfds)
+           *exceptfds = myexcept;
+       ret = n;
+       goto out;
+    }
+    errno = EINTR;
+    ret = -1;
+
+out:
+    remove_waiter(w1);
+    remove_waiter(w2);
+    remove_waiter(w3);
+    remove_waiter(w4);
+    return ret;
+}
+
+int socket(int domain, int type, int protocol)
+{
+    int fd, res;
+    fd = lwip_socket(domain, type, protocol);
+    if (fd < 0)
+       return -1;
+    res = alloc_fd(FTYPE_SOCKET);
+    printk("socket -> %d\n", res);
+    files[res].socket.fd = fd;
+    return res;
+}
+
+int accept(int s, struct sockaddr *addr, socklen_t *addrlen)
+{
+    int fd, res;
+    if (files[s].type != FTYPE_SOCKET) {
+       printk("accept(%d): Bad descriptor\n", s);
+       errno = EBADF;
+       return -1;
+    }
+    fd = lwip_accept(files[s].socket.fd, addr, addrlen);
+    if (fd < 0)
+       return -1;
+    res = alloc_fd(FTYPE_SOCKET);
+    files[res].socket.fd = fd;
+    printk("accepted on %d -> %d\n", s, res);
+    return res;
+}
+
+#define LWIP_STUB(ret, name, proto, args) \
+ret name proto \
+{ \
+    if (files[s].type != FTYPE_SOCKET) { \
+       printk(#name "(%d): Bad descriptor\n", s); \
+       errno = EBADF; \
+       return -1; \
+    } \
+    s = files[s].socket.fd; \
+    return lwip_##name args; \
+}
+
+LWIP_STUB(int, bind, (int s, struct sockaddr *my_addr, socklen_t addrlen), (s, 
my_addr, addrlen))
+LWIP_STUB(int, getsockopt, (int s, int level, int optname, void *optval, 
socklen_t *optlen), (s, level, optname, optval, optlen))
+LWIP_STUB(int, setsockopt, (int s, int level, int optname, void *optval, 
socklen_t optlen), (s, level, optname, optval, optlen))
+LWIP_STUB(int, connect, (int s, struct sockaddr *serv_addr, socklen_t 
addrlen), (s, serv_addr, addrlen))
+LWIP_STUB(int, listen, (int s, int backlog), (s, backlog));
+LWIP_STUB(ssize_t, recv, (int s, void *buf, size_t len, int flags), (s, buf, 
len, flags))
+LWIP_STUB(ssize_t, recvfrom, (int s, void *buf, size_t len, int flags, struct 
sockaddr *from, socklen_t *fromlen), (s, buf, len, flags, from, fromlen))
+LWIP_STUB(ssize_t, send, (int s, void *buf, size_t len, int flags), (s, buf, 
len, flags))
+LWIP_STUB(ssize_t, sendto, (int s, void *buf, size_t len, int flags, struct 
sockaddr *to, socklen_t tolen), (s, buf, len, flags, to, tolen))
+LWIP_STUB(int, getsockname, (int s, struct sockaddr *name, socklen_t 
*namelen), (s, name, namelen))
+
+int nanosleep(const struct timespec *req, struct timespec *rem)
+{
+    s_time_t start = NOW();
+    s_time_t stop = start + SECONDS(req->tv_sec) + req->tv_nsec;
+    s_time_t stopped;
+    struct thread *thread = get_current();
+
+    thread->wakeup_time = stop;
+    clear_runnable(thread);
+    schedule();
+    stopped = NOW();
+
+    if (rem)
+    {
+       s_time_t remaining = stop - stopped;
+       if (remaining > 0)
+       {
+           rem->tv_nsec = remaining % 1000000000ULL;
+           rem->tv_sec  = remaining / 1000000000ULL;
+       } else memset(rem, 0, sizeof(*rem));
+    }
+
+    return 0;
+}
+
+int usleep(useconds_t usec)
+{
+    /* "usec shall be less than one million."  */
+    struct timespec req;
+    req.tv_nsec = usec * 1000;
+    req.tv_sec = 0;
+
+    if (nanosleep(&req, NULL))
+       return -1;
+
+    return 0;
+}
+
+unsigned int sleep(unsigned int seconds)
+{
+    struct timespec req, rem;
+    req.tv_sec = seconds;
+    req.tv_nsec = 0;
+
+    if (nanosleep(&req, &rem))
+       return -1;
+
+    if (rem.tv_nsec > 0)
+       rem.tv_sec++;
+
+    return rem.tv_sec;
+}
+
+int clock_gettime(clockid_t clk_id, struct timespec *tp)
+{
+    switch (clk_id) {
+       case CLOCK_MONOTONIC:
+       {
+           struct timeval tv;
+
+           gettimeofday(&tv, NULL);
+
+           tp->tv_sec = tv.tv_sec;
+           tp->tv_nsec = tv.tv_usec * 1000;
+
+           break;
+       }
+       case CLOCK_REALTIME:
+       {
+           u64 nsec = monotonic_clock();
+
+           tp->tv_sec = nsec / 1000000000ULL;
+           tp->tv_nsec = nsec % 1000000000ULL;
+
+           break;
+       }
+       default:
+           print_unsupported("clock_gettime(%d)", clk_id);
+           errno = EINVAL;
+           return -1;
+    }
+
+    return 0;
+}
+
+void *mmap(void *start, size_t length, int prot, int flags, int fd, off_t 
offset)
+{
+    ASSERT(!start);
+    length = (length + PAGE_SIZE - 1) & PAGE_MASK;
+    ASSERT(prot == (PROT_READ|PROT_WRITE));
+    ASSERT(flags == (MAP_SHARED|MAP_ANON) || flags == (MAP_PRIVATE|MAP_ANON));
+    ASSERT(fd == -1);
+    ASSERT(offset == 0);
+
+    return map_zero(length / PAGE_SIZE, 1);
+}
+#if defined(__x86_64__) || defined(__ia64__)
+__typeof__(mmap) mmap64 __attribute__((__alias__("mmap")));
+#endif
+
+int munmap(void *start, size_t length)
+{
+    int i, n = length / PAGE_SIZE;
+    multicall_entry_t call[n];
+    unsigned char (*data)[PAGE_SIZE] = start;
+    int ret;
+    ASSERT(!((unsigned long)start & ~PAGE_MASK));
+    ASSERT(!(length & ~PAGE_MASK));
+
+    for (i = 0; i < n; i++) {
+       call[i].op = __HYPERVISOR_update_va_mapping;
+       call[i].args[0] = (unsigned long) &data[i];
+       call[i].args[1] = 0;
+       call[i].args[2] = 0;
+       call[i].args[3] = UVMF_INVLPG | UVMF_ALL;
+    }
+
+    ret = HYPERVISOR_multicall(call, n);
+    if (ret) {
+       errno = -ret;
+       return -1;
+    }
+
+    for (i = 0; i < n; i++) {
+       if (call[i].result) {
+           errno = call[i].result;
+           return -1;
+       }
+    }
+    return 0;
+}
+
+/* Not supported by FS yet.  */
+unsupported_function_crash(link);
+unsupported_function(int, readlink, -1);
+
+/* We could support that.  */
+unsupported_function_log(int, chdir, -1);
+
+/* No dynamic library support.  */ 
+unsupported_function_log(void *, dlopen, NULL);
+unsupported_function_log(void *, dlsym, NULL);
+unsupported_function_log(char *, dlerror, NULL);
+unsupported_function_log(int, dlclose, -1);
+
+/* We don't raise signals anyway.  */
+unsupported_function(int, sigemptyset, -1);
+unsupported_function(int, sigfillset, -1);
+unsupported_function(int, sigaddset, -1);
+unsupported_function(int, sigdelset, -1);
+unsupported_function(int, sigismember, -1);
+unsupported_function(int, sigprocmask, -1);
+unsupported_function(int, sigaction, -1);
+unsupported_function(int, __sigsetjmp, 0);
+unsupported_function(int, sigaltstack, -1);
+unsupported_function_crash(kill);
+
+/* Linuxish abi for the Caml runtime, don't support */
+unsupported_function_log(struct dirent *, readdir64, NULL);
+unsupported_function_log(int, getrusage, -1);
+unsupported_function_log(int, getrlimit, -1);
+unsupported_function_log(int, getrlimit64, -1);
+unsupported_function_log(int, __xstat64, -1);
+unsupported_function_log(long, __strtol_internal, LONG_MIN);
+unsupported_function_log(double, __strtod_internal, HUGE_VAL);
+#endif
diff -r 7b0c0ab0566b extras/mini-os/lib/xs.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/extras/mini-os/lib/xs.c   Mon Feb 11 17:16:12 2008 +0000
@@ -0,0 +1,187 @@
+/*
+ * libxs-compatible layer
+ *
+ * Samuel Thibault <Samuel.Thibault@xxxxxxxxxxxxx>, 2007-2008
+ *
+ * Mere wrapper around xenbus_*
+ */
+
+#ifdef HAVE_LIBC
+#include <os.h>
+#include <lib.h>
+#include <xs.h>
+#include <xenbus.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+static inline int _xs_fileno(struct xs_handle *h) {
+    return (intptr_t) h;
+}
+
+struct xs_handle *xs_daemon_open()
+{
+    int fd = alloc_fd(FTYPE_XENBUS);
+    files[fd].xenbus.events = NULL;
+    printk("xs_daemon_open -> %d, %p\n", fd, &files[fd].xenbus.events);
+    return (void*)(intptr_t) fd;
+}
+
+void xs_daemon_close(struct xs_handle *h)
+{
+    int fd = _xs_fileno(h);
+    struct xenbus_event *event;
+    for (event = files[fd].xenbus.events; event; event = event->next)
+        free(event);
+    files[fd].type = FTYPE_NONE;
+}
+
+int xs_fileno(struct xs_handle *h)
+{
+    return _xs_fileno(h);
+}
+
+void *xs_read(struct xs_handle *h, xs_transaction_t t,
+            const char *path, unsigned int *len)
+{
+    char *value;
+    char *msg;
+
+    msg = xenbus_read(t, path, &value);
+    if (msg) {
+       printk("xs_read(%s): %s\n", path, msg);
+       return NULL;
+    }
+
+    if (len)
+       *len = strlen(value);
+    return value;
+}
+
+bool xs_write(struct xs_handle *h, xs_transaction_t t,
+             const char *path, const void *data, unsigned int len)
+{
+    char value[len + 1];
+    char *msg;
+
+    memcpy(value, data, len);
+    value[len] = 0;
+
+    msg = xenbus_write(t, path, value);
+    if (msg) {
+       printk("xs_write(%s): %s\n", path, msg);
+       return false;
+    }
+    return true;
+}
+
+static bool xs_bool(char *reply)
+{
+    if (!reply)
+       return true;
+    free(reply);
+    return false;
+}
+
+bool xs_rm(struct xs_handle *h, xs_transaction_t t, const char *path)
+{
+    return xs_bool(xenbus_rm(t, path));
+}
+
+static void *xs_talkv(struct xs_handle *h, xs_transaction_t t,
+               enum xsd_sockmsg_type type,
+               struct write_req *iovec,
+               unsigned int num_vecs,
+               unsigned int *len)
+{
+    struct xsd_sockmsg *msg;
+    void *ret;
+
+    msg = xenbus_msg_reply(type, t, iovec, num_vecs);
+    ret = malloc(msg->len);
+    memcpy(ret, (char*) msg + sizeof(*msg), msg->len);
+    if (len)
+       *len = msg->len - 1;
+    free(msg);
+    return ret;
+}
+
+static void *xs_single(struct xs_handle *h, xs_transaction_t t,
+               enum xsd_sockmsg_type type,
+               const char *string,
+               unsigned int *len)
+{
+    struct write_req iovec;
+
+    iovec.data = (void *)string;
+    iovec.len = strlen(string) + 1;
+
+    return xs_talkv(h, t, type, &iovec, 1, len);
+}
+
+char *xs_get_domain_path(struct xs_handle *h, unsigned int domid)
+{
+    char domid_str[MAX_STRLEN(domid)];
+
+    sprintf(domid_str, "%u", domid);
+
+    return xs_single(h, XBT_NULL, XS_GET_DOMAIN_PATH, domid_str, NULL);
+}
+
+char **xs_directory(struct xs_handle *h, xs_transaction_t t,
+                   const char *path, unsigned int *num)
+{
+    char *msg;
+    char **entries, **res;
+    char *entry;
+    int i, n;
+    int size;
+
+    msg = xenbus_ls(t, path, &res);
+    if (msg) {
+       printk("xs_directory(%s): %s\n", path, msg);
+       return NULL;
+    }
+
+    size = 0;
+    for (n = 0; res[n]; n++)
+       size += strlen(res[n]) + 1;
+
+    entries = malloc(n * sizeof(char *) + size);
+    entry = (char *) (&entries[n]);
+
+    for (i = 0; i < n; i++) {
+       int l = strlen(res[i]) + 1;
+       memcpy(entry, res[i], l);
+       free(res[i]);
+       entries[i] = entry;
+       entry += l;
+    }
+
+    *num = n;
+    return entries;
+}
+
+bool xs_watch(struct xs_handle *h, const char *path, const char *token)
+{
+    int fd = _xs_fileno(h);
+    printk("xs_watch(%s, %s)\n", path, token);
+    return xs_bool(xenbus_watch_path_token(XBT_NULL, path, token, 
&files[fd].xenbus.events));
+}
+
+char **xs_read_watch(struct xs_handle *h, unsigned int *num)
+{
+    int fd = _xs_fileno(h);
+    struct xenbus_event *event;
+    event = files[fd].xenbus.events;
+    files[fd].xenbus.events = event->next;
+    printk("xs_read_watch() -> %s %s\n", event->path, event->token);
+    *num = 2;
+    return (char **) &event->path;
+}
+
+bool xs_unwatch(struct xs_handle *h, const char *path, const char *token)
+{
+    printk("xs_unwatch(%s, %s)\n", path, token);
+    return xs_bool(xenbus_unwatch_path_token(XBT_NULL, path, token));
+}
+#endif
diff -r 7b0c0ab0566b extras/mini-os/main-caml.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/extras/mini-os/main-caml.c        Mon Feb 11 17:16:12 2008 +0000
@@ -0,0 +1,42 @@
+/*
+ * Caml bootstrap
+ *
+ * Samuel Thibault <Samuel.Thibault@xxxxxxxxxxxxx>, January 2008
+ */
+
+#include <stdio.h>
+#include <errno.h>
+
+#include <caml/mlvalues.h>
+#include <caml/callback.h>
+#include <unistd.h>
+
+/* Ugly binary compatibility with Linux */
+FILE *_stderr asm("stderr");
+int *__errno_location;
+/* Will probably break everything, probably need to fetch from glibc */
+void *__ctype_b_loc;
+
+int main(int argc, char *argv[], char *envp[])
+{
+    value *val;
+
+    /* Get current thread's value */
+    _stderr = stderr;
+    __errno_location = &errno;
+
+    printf("starting caml\n");
+
+    /* Wait before things might hang up */
+    sleep(1);
+
+    caml_startup(argv);
+    val = caml_named_value("main");
+    if (!val) {
+        printf("Couldn't find Caml main");
+        return 1;
+    }
+    caml_callback(*val, Val_int(0));
+    printf("callback returned\n");
+    return 0;
+}
diff -r 7b0c0ab0566b extras/mini-os/main.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/extras/mini-os/main.c     Mon Feb 11 17:16:12 2008 +0000
@@ -0,0 +1,167 @@
+/*
+ * POSIX-compatible main layer
+ *
+ * Samuel Thibault <Samuel.Thibault@xxxxxxxxxxxxx>, October 2007
+ */
+
+#ifdef HAVE_LIBC
+#include <os.h>
+#include <sched.h>
+#include <console.h>
+#include <netfront.h>
+#include <time.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fs.h>
+#include <xenbus.h>
+#include <events.h>
+
+extern int main(int argc, char *argv[], char *envp[]);
+extern void __libc_init_array(void);
+extern void __libc_fini_array(void);
+
+struct thread *main_thread;
+
+#if 0
+#include <stdio.h>
+int main(int argc, char *argv[], char *envp[])
+{
+    printf("Hello, World!\n");
+    return 1;
+}
+#endif
+
+void _init(void)
+{
+}
+
+void _fini(void)
+{
+}
+
+static void call_main(void *p)
+{
+    char *args, /**path,*/ *msg, *c;
+    int argc;
+    char **argv;
+    char *envp[] = { NULL };
+    char *vm;
+    int i;
+    char path[128];
+
+    /* Let other parts initialize (including console output) before maybe
+     * crashing. */
+    //sleep(1);
+
+    start_networking();
+    init_fs_frontend();
+
+#ifdef CONFIG_QEMU
+    if (!fs_import) {
+        printk("No FS backend found, is it running?\n");
+        do_exit();
+    }
+
+    /* Fetch argc, argv from XenStore */
+    char domid_s[10];
+    int domid;
+    domid = xenbus_read_integer("target");
+    if (domid == -1) {
+        printk("Couldn't read target\n");
+        do_exit();
+    }
+    snprintf(domid_s, sizeof(domid_s), "%d", domid);
+
+    snprintf(path, sizeof(path), "/local/domain/%d/vm", domid);
+    msg = xenbus_read(XBT_NIL, path, &vm);
+    if (msg) {
+        printk("Couldn't read vm path\n");
+        do_exit();
+    }
+    printk("vm is at %s\n", vm);
+#else
+    msg = xenbus_read(XBT_NIL, "vm", &vm);
+    if (msg) {
+        printk("Couldn't read vm path\n");
+        do_exit();
+    }
+#endif
+
+    snprintf(path, sizeof(path), "%s/image/dmargs", vm);
+    free(vm);
+    msg = xenbus_read(XBT_NIL, path, &args);
+
+    if (msg) {
+        printk("Couldn't get stubdom args: %s\n", msg);
+        args = strdup("");
+    }
+
+    argc = 1;
+#ifdef CONFIG_QEMU
+    argc += 2;
+#endif
+    c = args;
+    while (*c) {
+       if (*c != ' ') {
+           argc++;
+           while (*c && *c != ' ')
+               c++;
+       } else {
+           while (*c == ' ')
+               c++;
+       }
+    }
+    argv = alloca((argc + 1) * sizeof(char *));
+    argv[0] = "main";
+    argc = 1;
+#ifdef CONFIG_QEMU
+    argv[1] = "-d";
+    argv[2] = domid_s;
+    argc += 2;
+#endif
+    c = args;
+    while (*c) {
+       if (*c != ' ') {
+           argv[argc++] = c;
+           while (*c && *c != ' ')
+               c++;
+       } else {
+           *c++ = 0;
+           while (*c == ' ')
+               c++;
+       }
+    }
+    argv[argc] = NULL;
+
+    for (i = 0; i < argc; i++)
+       printf("\"%s\" ", argv[i]);
+    printf("\n");
+
+    __libc_init_array();
+    environ = envp;
+    tzset();
+
+    exit(main(argc, argv, envp));
+}
+
+void _exit(int ret)
+{
+    close_all_files();
+    __libc_fini_array();
+    printk("main returned %d\n", ret);
+    unbind_all_ports();
+    if (!ret) {
+       /* No problem, just shutdown.  */
+        struct sched_shutdown sched_shutdown = { .reason = SHUTDOWN_poweroff };
+        HYPERVISOR_sched_op(SCHEDOP_shutdown, &sched_shutdown);
+    }
+    do_exit();
+}
+
+int app_main(start_info_t *si)
+{
+    printk("Dummy main: start_info=%p\n", si);
+    main_thread = create_thread("main", call_main, si);
+    return 0;
+}
+#endif
diff -r 7b0c0ab0566b extras/mini-os/minios.mk
--- a/extras/mini-os/minios.mk  Mon Feb 11 14:55:33 2008 +0000
+++ b/extras/mini-os/minios.mk  Mon Feb 11 17:16:12 2008 +0000
@@ -9,7 +9,7 @@ DEF_CFLAGS += -fno-builtin -Wall -Werror
 DEF_CFLAGS += -fno-builtin -Wall -Werror -Wredundant-decls -Wno-format
 DEF_CFLAGS += $(call cc-option,$(CC),-fno-stack-protector,)
 DEF_CFLAGS += -Wstrict-prototypes -Wnested-externs -Wpointer-arith -Winline
-DEF_CFLAGS += -D__XEN_INTERFACE_VERSION__=$(XEN_INTERFACE_VERSION)
+DEF_CPPFLAGS += -D__XEN_INTERFACE_VERSION__=$(XEN_INTERFACE_VERSION)
 
 DEF_ASFLAGS = -D__ASSEMBLY__
 DEF_LDFLAGS =
@@ -24,11 +24,9 @@ endif
 # DEF_... flags are the common mini-os flags,
 # ARCH_... flags may be defined in arch/$(TARGET_ARCH_FAM/rules.mk
 CFLAGS := $(DEF_CFLAGS) $(ARCH_CFLAGS)
+CPPFLAGS := $(DEF_CPPFLAGS) $(ARCH_CPPFLAGS)
 ASFLAGS := $(DEF_ASFLAGS) $(ARCH_ASFLAGS)
 LDFLAGS := $(DEF_LDFLAGS) $(ARCH_LDFLAGS)
-
-# The path pointing to the architecture specific header files.
-ARCH_INC := $(MINI-OS_ROOT)/include/$(TARGET_ARCH_FAM)
 
 # Special build dependencies.
 # Rebuild all after touching this/these file(s)
@@ -44,18 +42,17 @@ HDRS += $(extra_heads)
 HDRS += $(extra_heads)
 
 # Add the special header directories to the include paths.
-extra_incl := $(foreach dir,$(EXTRA_INC),-I$(MINI-OS_ROOT)/include/$(dir))
-override CPPFLAGS := -I$(MINI-OS_ROOT)/include $(CPPFLAGS) -I$(ARCH_INC)       
$(extra_incl)
+override CPPFLAGS := $(CPPFLAGS) $(extra_incl)
 
 # The name of the architecture specific library.
 # This is on x86_32: libx86_32.a
 # $(ARCH_LIB) has to built in the architecture specific directory.
-ARCH_LIB_NAME = $(TARGET_ARCH)
+ARCH_LIB_NAME = $(XEN_TARGET_ARCH)
 ARCH_LIB := lib$(ARCH_LIB_NAME).a
 
 # This object contains the entrypoint for startup from Xen.
 # $(HEAD_ARCH_OBJ) has to be built in the architecture specific directory.
-HEAD_ARCH_OBJ := $(TARGET_ARCH).o
+HEAD_ARCH_OBJ := $(XEN_TARGET_ARCH).o
 HEAD_OBJ := $(TARGET_ARCH_DIR)/$(HEAD_ARCH_OBJ)
 
 
diff -r 7b0c0ab0566b extras/mini-os/mm.c
--- a/extras/mini-os/mm.c       Mon Feb 11 14:55:33 2008 +0000
+++ b/extras/mini-os/mm.c       Mon Feb 11 17:16:12 2008 +0000
@@ -360,6 +360,29 @@ void free_pages(void *pointer, int order
    
 }
 
+#ifdef HAVE_LIBC
+void *sbrk(ptrdiff_t increment)
+{
+    unsigned long old_brk = brk;
+    unsigned long new_brk = old_brk + increment;
+
+    if (new_brk > heap_end) {
+       printk("Heap exhausted: %p + %lx = %p > %p\n", old_brk, increment, 
new_brk, heap_end);
+       return NULL;
+    }
+    
+    if (new_brk > heap_mapped) {
+        unsigned long n = (new_brk - heap_mapped + PAGE_SIZE - 1) / PAGE_SIZE;
+        do_map_zero(heap_mapped, n);
+        heap_mapped += n * PAGE_SIZE;
+    }
+
+    brk = new_brk;
+
+    return (void *) old_brk;
+}
+#endif
+
 
 
 void init_mm(void)
diff -r 7b0c0ab0566b extras/mini-os/netfront.c
--- a/extras/mini-os/netfront.c Mon Feb 11 14:55:33 2008 +0000
+++ b/extras/mini-os/netfront.c Mon Feb 11 17:16:12 2008 +0000
@@ -19,7 +19,10 @@
 
 DECLARE_WAIT_QUEUE_HEAD(netfront_queue);
 
+#ifdef HAVE_LIBC
 #define NETIF_SELECT_RX ((void*)-1)
+#endif
+
 
 
 #define NET_TX_RING_SIZE __RING_SIZE((struct netif_tx_sring *)0, PAGE_SIZE)
@@ -49,6 +52,13 @@ struct netfront_dev {
 
     char *nodename;
     char *backend;
+
+#ifdef HAVE_LIBC
+    int fd;
+    unsigned char *data;
+    size_t len;
+    size_t rlen;
+#endif
 
     void (*netif_rx)(unsigned char* data, int len);
 };
@@ -92,7 +102,8 @@ moretodo:
     cons = dev->rx.rsp_cons;
 
     int nr_consumed=0;
-    while ((cons != rp))
+    int some = 0;
+    while ((cons != rp) && !some)
     {
         struct net_buffer* buf;
         unsigned char* page;
@@ -116,7 +127,18 @@ moretodo:
 
         if(rx->status>0)
         {
-            dev->netif_rx(page+rx->offset,rx->status);
+#ifdef HAVE_LIBC
+           if (dev->netif_rx == NETIF_SELECT_RX) {
+               int len = rx->status;
+               ASSERT(current == main_thread);
+               if (len > dev->len)
+                   len = dev->len;
+               memcpy(dev->data, page+rx->offset, len);
+               dev->rlen = len;
+               some = 1;
+           } else
+#endif
+               dev->netif_rx(page+rx->offset,rx->status);
         }
 
         nr_consumed++;
@@ -127,7 +149,7 @@ moretodo:
 
     int more;
     RING_FINAL_CHECK_FOR_RESPONSES(&dev->rx,more);
-    if(more) goto moretodo;
+    if(more && !some) goto moretodo;
 
     RING_IDX req_prod = dev->rx.req_prod_pvt;
 
@@ -178,6 +200,9 @@ void network_tx_buf_gc(struct netfront_d
             if (txrsp->status == NETIF_RSP_NULL)
                 continue;
 
+            if (txrsp->status == NETIF_RSP_ERROR)
+                printk("packet error\n");
+
             id  = txrsp->id;
             struct net_buffer* buf = &dev->tx_buffers[id];
             gnttab_end_access(buf->gref);
@@ -217,6 +242,22 @@ void netfront_handler(evtchn_port_t port
 
     local_irq_restore(flags);
 }
+
+#ifdef HAVE_LIBC
+void netfront_select_handler(evtchn_port_t port, struct pt_regs *regs, void 
*data)
+{
+    int flags;
+    struct netfront_dev *dev = data;
+    int fd = dev->fd;
+
+    local_irq_save(flags);
+    network_tx_buf_gc(dev);
+    local_irq_restore(flags);
+
+    files[fd].read = 1;
+    wake_up(&netfront_queue);
+}
+#endif
 
 struct netfront_dev *init_netfront(char *nodename, void 
(*thenetif_rx)(unsigned char* data, int len), unsigned char rawmac[6])
 {
@@ -266,7 +307,12 @@ struct netfront_dev *init_netfront(char 
     dev->dom = op.remote_dom = xenbus_read_integer(path);
     HYPERVISOR_event_channel_op(EVTCHNOP_alloc_unbound, &op);
     clear_evtchn(op.port);        /* Without, handler gets invoked now! */
-    dev->local_port = bind_evtchn(op.port, netfront_handler, dev);
+#ifdef HAVE_LIBC
+    if (thenetif_rx == NETIF_SELECT_RX)
+       dev->local_port = bind_evtchn(op.port, netfront_select_handler, dev);
+    else
+#endif
+       dev->local_port = bind_evtchn(op.port, netfront_handler, dev);
     dev->evtchn=op.port;
 
     txs = (struct netif_tx_sring*) alloc_page();
@@ -381,6 +427,23 @@ done:
     return dev;
 }
 
+#ifdef HAVE_LIBC
+int netfront_tap_open(char *nodename) {
+    struct netfront_dev *dev;
+
+    dev = init_netfront(nodename, NETIF_SELECT_RX, NULL);
+    if (!dev) {
+       printk("TAP open failed\n");
+       errno = EIO;
+       return -1;
+    }
+    dev->fd = alloc_fd(FTYPE_TAP);
+    printk("tap_open(%s) -> %d\n", nodename, dev->fd);
+    files[dev->fd].tap.dev = dev;
+    return dev->fd;
+}
+#endif
+
 void shutdown_netfront(struct netfront_dev *dev)
 {
     char* err;
@@ -481,3 +544,30 @@ void netfront_xmit(struct netfront_dev *
     network_tx_buf_gc(dev);
     local_irq_restore(flags);
 }
+
+#ifdef HAVE_LIBC
+ssize_t netfront_receive(struct netfront_dev *dev, unsigned char *data, size_t 
len)
+{
+    unsigned long flags;
+    int fd = dev->fd;
+    ASSERT(current == main_thread);
+
+    dev->rlen = 0;
+    dev->data = data;
+    dev->len = len;
+
+    local_irq_save(flags);
+    network_rx(dev);
+    if (!dev->rlen)
+       /* No data for us, make select stop returning */
+       files[fd].read = 0;
+    /* Before re-enabling the interrupts, in case a packet just arrived in the
+     * meanwhile. */
+    local_irq_restore(flags);
+
+    dev->data = NULL;
+    dev->len = 0;
+
+    return dev->rlen;
+}
+#endif
diff -r 7b0c0ab0566b extras/mini-os/sched.c
--- a/extras/mini-os/sched.c    Mon Feb 11 14:55:33 2008 +0000
+++ b/extras/mini-os/sched.c    Mon Feb 11 17:16:12 2008 +0000
@@ -56,6 +56,7 @@
 
 struct thread *idle_thread = NULL;
 LIST_HEAD(exited_threads);
+static int threads_started;
 
 void inline print_runqueue(void)
 {
@@ -172,6 +173,9 @@ struct thread* create_thread(char *name,
     /* Not runable, not exited, not sleeping */
     thread->flags = 0;
     thread->wakeup_time = 0LL;
+#ifdef HAVE_LIBC
+    _REENT_INIT_PTR((&thread->reent))
+#endif
     set_runnable(thread);
     local_irq_save(flags);
     if(idle_thread != NULL) {
@@ -184,6 +188,42 @@ struct thread* create_thread(char *name,
     local_irq_restore(flags);
     return thread;
 }
+
+#ifdef HAVE_LIBC
+static struct _reent callback_reent;
+struct _reent *__getreent(void)
+{
+    struct _reent *_reent;
+
+    if (!threads_started)
+       _reent = _impure_ptr;
+    else if (in_callback)
+       _reent = &callback_reent;
+    else
+       _reent = &get_current()->reent;
+
+#ifndef NDEBUG
+#if defined(__x86_64__) || defined(__x86__)
+    {
+#ifdef __x86_64__
+       register unsigned long sp asm ("rsp");
+#else
+       register unsigned long sp asm ("esp");
+#endif
+       if ((sp & (STACK_SIZE-1)) < STACK_SIZE / 16) {
+           static int overflowing;
+           if (!overflowing) {
+               overflowing = 1;
+               printk("stack overflow\n");
+               BUG();
+           }
+       }
+    }
+#endif
+#endif
+    return _reent;
+}
+#endif
 
 void exit_thread(void)
 {
@@ -228,6 +268,7 @@ void idle_thread_fn(void *unused)
 void idle_thread_fn(void *unused)
 {
     s_time_t until;
+    threads_started = 1;
     unsigned long flags;
     struct list_head *iterator;
     struct thread *next, *thread;
@@ -297,6 +338,9 @@ void init_sched(void)
 {
     printk("Initialising scheduler\n");
 
+#ifdef HAVE_LIBC
+    _REENT_INIT_PTR((&callback_reent))
+#endif
     idle_thread = create_thread("Idle", idle_thread_fn, NULL);
     INIT_LIST_HEAD(&idle_thread->thread_list);
 }
diff -r 7b0c0ab0566b stubdom/Makefile
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/stubdom/Makefile  Mon Feb 11 17:16:12 2008 +0000
@@ -0,0 +1,256 @@
+XEN_ROOT = ..
+
+include $(XEN_ROOT)/Config.mk
+export stubdom=y
+export debug=y
+
+IOEMU_OPTIONS=--disable-vnc-tls 
+BINUTILS_VERSION=2.18
+GCC_VERSION=4.2.2
+ZLIB_VERSION=1.2.3
+LIBPCI_VERSION=2.2.9
+NEWLIB_DATE=2008-01-01
+LWIP_DATE=2008-02-08
+
+WGET=wget -c
+
+GNU_TARGET_ARCH:=$(XEN_TARGET_ARCH)
+ifeq ($(XEN_TARGET_ARCH),x86_32)
+GNU_TARGET_ARCH:=i386
+endif
+
+ifeq ($(GNU_TARGET_ARCH), i386)
+TARGET_CFLAGS=
+endif
+ifeq ($(GNU_TARGET_ARCH), x86_64)
+TARGET_CFLAGS=-mno-red-zone
+endif
+ifeq ($(GNU_TARGET_ARCH), ia64)
+TARGET_CFLAGS=-mconstant-gp
+endif
+
+CROSS_ROOT=cross-root-$(GNU_TARGET_ARCH)
+CROSS_PREFIX=$(CURDIR)/$(CROSS_ROOT)
+export CROSS_COMPILE=$(GNU_TARGET_ARCH)-xen-elf-
+export PATH:=$(CROSS_PREFIX)/bin:$(PATH)
+
+.PHONY: all
+all: qemu-stubdom
+
+################
+# Cross-binutils
+################
+
+binutils-$(BINUTILS_VERSION).tar.bz2:
+       $(WGET) http://ftp.gnu.org/gnu/binutils/$@
+binutils-$(BINUTILS_VERSION): binutils-$(BINUTILS_VERSION).tar.bz2
+       tar xjf $@.tar.bz2
+       ( cd binutils-$(BINUTILS_VERSION) && patch -p1 < ../binutils.patch )
+       touch $@
+
+BINUTILS_STAMPFILE=$(CROSS_ROOT)/bin/$(GNU_TARGET_ARCH)-xen-elf-ar
+.PHONY: cross-binutils
+cross-binutils: $(BINUTILS_STAMPFILE)
+$(BINUTILS_STAMPFILE): binutils-$(BINUTILS_VERSION)
+       mkdir -p binutils.build
+       ( cd binutils.build && \
+         ../binutils-$(BINUTILS_VERSION)/configure --prefix=$(CROSS_PREFIX) 
--verbose --target=$(GNU_TARGET_ARCH)-xen-elf && \
+         $(MAKE) && \
+         $(MAKE) check && \
+         $(MAKE) install )
+
+###########
+# Cross-gcc
+###########
+
+gcc-$(GCC_VERSION).tar.bz2:
+       $(WGET) 
http://ftp.gnu.org/gnu/gcc/gcc-$(GCC_VERSION)/gcc-$(GCC_VERSION).tar.bz2
+gcc-$(GCC_VERSION): gcc-$(GCC_VERSION).tar.bz2
+       tar xjf gcc-$(GCC_VERSION).tar.bz2
+       ( cd gcc-$(GCC_VERSION) && patch -p1 < ../gcc.patch )
+       touch $@
+       
+GCC_STAMPFILE=$(CROSS_ROOT)/bin/$(GNU_TARGET_ARCH)-xen-elf-gcc-$(GCC_VERSION)
+.PHONY: cross-gcc
+cross-gcc: $(GCC_STAMPFILE)
+$(GCC_STAMPFILE): gcc-$(GCC_VERSION) $(BINUTILS_STAMPFILE)
+       mkdir -p gcc.build
+       ( cd gcc.build && \
+         ../gcc-$(GCC_VERSION)/configure --prefix=$(CROSS_PREFIX) --verbose 
--target=$(GNU_TARGET_ARCH)-xen-elf --enable-languages=c --disable-libssp 
--with-gnu-as --with-gnu-ld && \
+         $(MAKE) GCC_FOR_TARGET='$$$$r/gcc/xgcc -B$$$$r/gcc/ 
'"$(TARGET_CFLAGS)"' $$(FLAGS_FOR_TARGET)' && \
+         $(MAKE) install )
+
+##############
+# Cross-newlib
+##############
+
+newlib:
+       cvs -z 9 -d :pserver:anoncvs@xxxxxxxxxxxxxxxxxx:/cvs/src co -D 
$(NEWLIB_DATE) newlib
+       mv src newlib
+       ( cd newlib && patch -p0 < ../newlib.patch)
+
+NEWLIB_STAMPFILE=$(CROSS_ROOT)/$(GNU_TARGET_ARCH)-xen-elf/lib/libc.a
+.PHONY: cross-newlib
+cross-newlib: $(NEWLIB_STAMPFILE)
+$(NEWLIB_STAMPFILE): newlib $(GCC_STAMPFILE)
+       mkdir -p newlib.build
+       ( cd newlib.build && \
+         CC_FOR_TARGET="$(GNU_TARGET_ARCH)-xen-elf-gcc $(TARGET_CFLAGS)" 
../newlib/configure --prefix=$(CROSS_PREFIX) --verbose 
--target=$(GNU_TARGET_ARCH)-xen-elf --enable-newlib-io-long-long && \
+         $(MAKE) && \
+         $(MAKE) install )
+
+############
+# Cross-zlib
+############
+
+zlib-$(ZLIB_VERSION).tar.gz:
+       $(WGET) http://www.zlib.net/zlib-$(ZLIB_VERSION).tar.gz
+
+ZLIB_STAMPFILE=$(CROSS_ROOT)/$(GNU_TARGET_ARCH)-xen-elf/lib/libz.a
+.PHONY: cross-zlib
+cross-zlib: $(ZLIB_STAMPFILE)
+$(ZLIB_STAMPFILE): zlib-$(ZLIB_VERSION).tar.gz $(NEWLIB_STAMPFILE)
+       tar xzf $<
+       ( cd zlib-$(ZLIB_VERSION) && \
+         CFLAGS="$(TARGET_CFLAGS)" CC=$(GNU_TARGET_ARCH)-xen-elf-gcc 
./configure --prefix=$(CROSS_PREFIX)/$(GNU_TARGET_ARCH)-xen-elf && \
+         $(MAKE) libz.a && \
+         $(MAKE) install )
+
+##############
+# Cross-libpci
+##############
+
+pciutils-$(LIBPCI_VERSION).tar.bz2:
+       $(WGET) 
http://www.kernel.org/pub/software/utils/pciutils/pciutils-$(LIBPCI_VERSION).tar.bz2
+
+LIBPCI_STAMPFILE=$(CROSS_ROOT)/$(GNU_TARGET_ARCH)-xen-elf/lib/libpci.a
+.PHONY: cross-libpci
+cross-libpci: $(LIBPCI_STAMPFILE)
+$(LIBPCI_STAMPFILE): pciutils-$(LIBPCI_VERSION).tar.bz2 $(NEWLIB_STAMPFILE) 
$(ZLIB_STAMPFILE)
+       tar xjf $<
+       ( cd pciutils-$(LIBPCI_VERSION) && \
+         cp ../libpci.config.h lib/config.h && \
+         echo '#define PCILIB_VERSION "$(LIBPCI_VERSION)"' >> lib/config.h && \
+         cp ../libpci.config.mak lib/config.mk && \
+         $(MAKE) CC="$(GNU_TARGET_ARCH)-xen-elf-gcc $(TARGET_CFLAGS)" 
lib/libpci.a && \
+         $(INSTALL_DATA) lib/libpci.a 
$(CROSS_PREFIX)/$(GNU_TARGET_ARCH)-xen-elf/lib/ && \
+         $(INSTALL_DIR) $(CROSS_PREFIX)/$(GNU_TARGET_ARCH)-xen-elf/include/pci 
&& \
+         $(INSTALL_DATA) lib/{config,header,pci,types}.h 
$(CROSS_PREFIX)/$(GNU_TARGET_ARCH)-xen-elf/include/pci/ \
+       )
+
+######
+# lwIP
+######
+
+lwip:
+       cvs -d :pserver:anonymous@xxxxxxxxxxxxxxxxxxxxxxx:/sources/lwip co -D 
$(LWIP_DATE) lwip
+
+#######
+# Links
+#######
+
+.PHONY: $(CROSS_ROOT)
+$(CROSS_ROOT): cross-newlib cross-zlib cross-libpci
+
+.PHONY: mk-symlinks
+mk-symlinks:
+       [ -h include ] || ln -sf ../tools/include .
+       mkdir -p libxc
+       [ -h libxc/Makefile ] || ( cd libxc && \
+         ln -sf ../../tools/libxc/*.h . && \
+         ln -sf ../../tools/libxc/*.c . && \
+         ln -sf ../../tools/libxc/Makefile . )
+       mkdir -p libxc/$(XEN_TARGET_ARCH)
+       [ -h libxc/$(XEN_TARGET_ARCH) ] || ( cd libxc/$(XEN_TARGET_ARCH) && \
+         ln -sf ../../tools/libxc/$(XEN_TARGET_ARCH)/*.c . && \
+         ln -sf ../../tools/libxc/$(XEN_TARGET_ARCH)/*.h . && \
+         ln -sf ../../tools/libxc/$(XEN_TARGET_ARCH)/Makefile . )
+       mkdir -p ioemu
+       [ -h ioemu/Makefile ] || ( cd ioemu && \
+         ln -sf ../../tools/ioemu/* . && \
+         ([ ! -h config-host.h ] || rm -f config-host.h) && \
+         ([ ! -h config-host.mak ] || rm -f config-host.mak) )
+       [ -h mini-os ] || ln -sf ../extras/mini-os .
+
+#######
+# libxc
+#######
+
+.PHONY: libxc
+libxc: cross-zlib mk-symlinks
+       $(MAKE) -C $@
+
+#######
+# ioemu
+#######
+
+.PHONY: ioemu
+ioemu: cross-zlib cross-libpci mk-symlinks libxc
+       [ -f ioemu/config-host.mak ] || \
+         ( cd ioemu ; XEN_TARGET_ARCH=$(XEN_TARGET_ARCH) sh configure 
--prefix=/usr --enable-stubdom $(IOEMU_OPTIONS))
+       $(MAKE) -C ioemu LWIPDIR=$(CURDIR)/lwip
+
+######
+# caml
+######
+
+.PHONY: caml
+caml:
+       $(MAKE) -C $@
+
+########
+# minios
+########
+
+.PHONY: qemu-stubdom
+qemu-stubdom: mk-symlinks lwip libxc ioemu
+       $(MAKE) -C mini-os LWIPDIR=$(CURDIR)/lwip QEMUDIR=$(CURDIR)/ioemu
+
+.PHONY: caml-stubdom
+caml-stubdom: mk-symlinks lwip libxc cross-libpci caml
+       $(MAKE) -C mini-os LWIPDIR=$(CURDIR)/lwip CAMLDIR=$(CURDIR)/caml
+
+#########
+# install
+#########
+
+install: mini-os/mini-os.gz
+       $(INSTALL_PROG) stubdom-dm "$(DESTDIR)/usr/lib/xen/bin"
+       $(INSTALL_PROG) mini-os/mini-os.gz 
"$(DESTDIR)/usr/lib/xen/boot/stubdom.gz"
+
+#######
+# clean
+#######
+
+# Only clean the libxc/ioemu/mini-os part
+.PHONY: clean
+clean:
+       -$(MAKE) -C mini-os LWIPDIR=$(CURDIR)/lwip clean
+       $(MAKE) -C caml clean
+       rm -fr libxc ioemu mini-os include
+
+# clean the cross-compilation result
+.PHONY: crossclean
+crossclean: clean
+       rm -fr $(CROSS_ROOT)
+       rm -fr binutils.build gcc.build newlib.build
+       rm -fr zlib-$(ZLIB_VERSION) pciutils-$(LIBPCI_VERSION)
+
+# clean patched sources
+.PHONY: patchclean
+patchclean: crossclean
+       rm -fr binutils-$(BINUTILS_VERSION)
+       rm -fr gcc-$(GCC_VERSION)
+       rm -fr newlib
+       rm -fr lwip
+
+# clean downloads
+.PHONY: downloadclean
+downloadclean: patchclean
+       rm -f binutils-$(BINUTILS_VERSION).tar.bz2
+       rm -f gcc-$(GCC_VERSION).tar.bz2
+       rm -f zlib-$(ZLIB_VERSION).tar.gz
+       rm -f pciutils-$(LIBPCI_VERSION).tar.bz2
+
+.PHONY: distclean
+distclean: downloadclean
diff -r 7b0c0ab0566b stubdom/README
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/stubdom/README    Mon Feb 11 17:16:12 2008 +0000
@@ -0,0 +1,41 @@
+To compile
+==========
+
+Just run make -j 4, that will download / patch / compile
+Then make install to install the result.
+
+Also, run make and make install in $XEN_ROOT/tools/fs-back
+
+To run
+======
+
+mkdir -p /exports/usr/share/qemu
+ln -s /usr/share/qemu/keymaps /exports/usr/share/qemu
+/usr/sbin/fs-backend &
+
+
+In your HVM config "hvmconfig",
+
+- use VNC, set vnclisten to "172.30.206.1" for instance:
+
+vnc=1 
+vnclisten="172.30.206.1" 
+
+- use /usr/lib/xen/bin/stubdom-dm as dm script
+
+device_model = '/usr/lib/xen/bin/stubdom-dm'
+
+- comment the disk statement:
+#disk = [  'file:/tmp/install.iso,hdc:cdrom,r', 'phy:/dev/sda6,hda,w', 
'file:/tmp/test,hdb,r' ]
+
+Create /etc/xen/stubdom-hvmconfig ("hvmconfig" must match your main config 
file)
+with
+
+kernel="/usr/lib/xen/boot/stubdom.gz"
+vif=[ 'ip=172.30.206.1', 'ip=10.0.1.1,mac=aa:00:00:12:23:34']
+disk = [  'file:/tmp/install.iso,hdc:cdrom,r', 'phy:/dev/sda6,hda,w', 
'file:/tmp/test,hdb,r' ]
+
+where
+- 172.30.206.1 is the IP for vnc,
+- 'ip=10.0.1.1,mac=' is the same net configuration as in the hvmconfig script,
+- and disk = is the same block configuration as in the hvmconfig script.
diff -r 7b0c0ab0566b stubdom/binutils.patch
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/stubdom/binutils.patch    Mon Feb 11 17:16:12 2008 +0000
@@ -0,0 +1,14 @@
+It looks like binutils has troubles with makeinfo and the doc generation.
+We don't need it anyway
+
+--- binutils-2.18/bfd/Makefile.inorig  2008-01-16 16:17:43.004484000 +0000
++++ binutils-2.18/bfd/Makefile.in      2008-01-16 16:17:50.505526000 +0000
+@@ -271,7 +271,7 @@
+ INCDIR = $(srcdir)/../include
+ CSEARCH = -I. -I$(srcdir) -I$(INCDIR)
+ MKDEP = gcc -MM
+-SUBDIRS = doc po
++SUBDIRS = po
+ bfddocdir = doc
+ bfdlib_LTLIBRARIES = libbfd.la
+ AM_CFLAGS = $(WARN_CFLAGS)
diff -r 7b0c0ab0566b stubdom/caml/Makefile
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/stubdom/caml/Makefile     Mon Feb 11 17:16:12 2008 +0000
@@ -0,0 +1,18 @@
+XEN_ROOT = ../..
+
+include $(XEN_ROOT)/Config.mk
+
+OCAMLFIND=ocamlfind
+OCAMLOPT=ocamlopt
+
+OBJS := hello.cmx
+LIBS := 
+
+%.cmx: %.ml
+       $(OCAMLFIND) $(OCAMLOPT) -c $< -o $@
+
+caml.o: $(OBJS)
+       $(OCAMLFIND) $(OCAMLOPT) $(LIBS) $^ -output-obj -o $@
+
+clean:
+       rm -f *.o *.cmx *.cmi
diff -r 7b0c0ab0566b stubdom/caml/hello.ml
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/stubdom/caml/hello.ml     Mon Feb 11 17:16:12 2008 +0000
@@ -0,0 +1,4 @@
+let main arg =
+  Printf.printf "Hello, world!\n%!."
+
+let _ = Callback.register "main" main
diff -r 7b0c0ab0566b stubdom/gcc.patch
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/stubdom/gcc.patch Mon Feb 11 17:16:12 2008 +0000
@@ -0,0 +1,31 @@
+Backported from later versions
+
+--- gcc-4.2.2/gcc/config.gcc       2007-11-22 16:27:45.000000000 +0000
++++ gcc-4.2.2/gcc/config.gcc       2007-11-22 16:23:00.000000000 +0000
+@@ -1033,6 +1033,11 @@
+       tmake_file="i386/t-i386elf t-svr4"
+       use_fixproto=yes
+       ;;
++x86_64-*-elf*)
++      tm_file="${tm_file} i386/unix.h i386/att.h dbxelf.h elfos.h 
i386/i386elf.h i386/x86-64.h"
++      tmake_file="i386/t-i386elf t-svr4"
++      use_fixproto=yes
++      ;;
+ i[34567]86-sequent-ptx4* | i[34567]86-sequent-sysv4*)
+       if test x$gas = xyes
+       then
+
+We don't have a libc yet at this stage. Unused anyway
+
+--- gcc-4.2.2/gcc/unwind-generic.h.orig 2008-01-11 18:54:40.000000000 +0100
++++ gcc-4.2.2/gcc/unwind-generic.h      2008-01-11 18:54:31.000000000 +0100
+@@ -203,7 +203,6 @@
+    compatible with the standard ABI for IA-64, we inline these.  */
+ 
+ #ifdef __ia64__
+-#include <stdlib.h>
+ 
+ static inline _Unwind_Ptr
+ _Unwind_GetDataRelBase (struct _Unwind_Context *_C)
+Backported from later versions
+
diff -r 7b0c0ab0566b stubdom/libpci.config.h
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/stubdom/libpci.config.h   Mon Feb 11 17:16:12 2008 +0000
@@ -0,0 +1,5 @@
+#define PCI_OS_STUBDOM
+#define PCI_HAVE_STDINT_H
+#define PCI_PATH_IDS_DIR "."
+#define PCI_COMPRESSED_IDS
+#define PCI_IDS "pci.ids.gz"
diff -r 7b0c0ab0566b stubdom/libpci.config.mak
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/stubdom/libpci.config.mak Mon Feb 11 17:16:12 2008 +0000
@@ -0,0 +1,2 @@
+LIBZ=-lz
+LDLIBS+=$(LIBZ)
diff -r 7b0c0ab0566b stubdom/newlib.patch
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/stubdom/newlib.patch      Mon Feb 11 17:16:12 2008 +0000
@@ -0,0 +1,183 @@
+There is a mix between longs and long longs.
+
+Index: newlib/libc/include/inttypes.h
+===================================================================
+RCS file: /cvs/src/src/newlib/libc/include/inttypes.h,v
+retrieving revision 1.3
+diff -u -p -r1.3 inttypes.h
+--- newlib/libc/include/inttypes.h     16 Dec 2005 19:03:12 -0000      1.3
++++ newlib/libc/include/inttypes.h     8 Nov 2007 16:32:44 -0000
+@@ -163,12 +163,12 @@
+ 
+ 
+ /* 64-bit types */
+-#if __have_longlong64
+-#define __PRI64(x) __STRINGIFY(ll##x)
+-#define __SCN64(x) __STRINGIFY(ll##x)
+-#elif __have_long64
++#if __have_long64
+ #define __PRI64(x) __STRINGIFY(l##x)
+ #define __SCN64(x) __STRINGIFY(l##x)
++#elif __have_longlong64
++#define __PRI64(x) __STRINGIFY(ll##x)
++#define __SCN64(x) __STRINGIFY(ll##x)
+ #else
+ #define __PRI64(x) __STRINGIFY(x)
+ #define __SCN64(x) __STRINGIFY(x)
+@@ -217,12 +217,12 @@
+ #endif
+ 
+ /* max-bit types */
+-#if __have_longlong64
+-#define __PRIMAX(x) __STRINGIFY(ll##x)
+-#define __SCNMAX(x) __STRINGIFY(ll##x)
+-#elif __have_long64
++#if __have_long64
+ #define __PRIMAX(x) __STRINGIFY(l##x)
+ #define __SCNMAX(x) __STRINGIFY(l##x)
++#elif __have_longlong64
++#define __PRIMAX(x) __STRINGIFY(ll##x)
++#define __SCNMAX(x) __STRINGIFY(ll##x)
+ #else
+ #define __PRIMAX(x) __STRINGIFY(x)
+ #define __SCNMAX(x) __STRINGIFY(x)
+@@ -242,12 +242,12 @@
+ #define SCNxMAX               __SCNMAX(x)
+ 
+ /* ptr types */
+-#if __have_longlong64
+-#define __PRIPTR(x) __STRINGIFY(ll##x)
+-#define __SCNPTR(x) __STRINGIFY(ll##x)
+-#elif __have_long64
++#if __have_long64
+ #define __PRIPTR(x) __STRINGIFY(l##x)
+ #define __SCNPTR(x) __STRINGIFY(l##x)
++#elif __have_longlong64
++#define __PRIPTR(x) __STRINGIFY(ll##x)
++#define __SCNPTR(x) __STRINGIFY(ll##x)
+ #else
+ #define __PRIPTR(x) __STRINGIFY(x)
+ #define __SCNPTR(x) __STRINGIFY(x)
+
+Define the basic ia64 jump buffer
+
+Index: newlib/libc/include/machine/setjmp.h
+===================================================================
+RCS file: /cvs/src/src/newlib/libc/include/machine/setjmp.h,v
+retrieving revision 1.34
+diff -u -p -r1.34 setjmp.h
+--- newlib/libc/include/machine/setjmp.h       7 Nov 2007 21:42:24 -0000       
1.34
++++ newlib/libc/include/machine/setjmp.h       11 Jan 2008 18:10:43 -0000
+@@ -72,6 +72,11 @@ _BEGIN_STD_C
+ #define _JBLEN  8
+ #endif
+ 
++#ifdef __ia64__
++#define _JBTYPE long
++#define _JBLEN 70
++#endif
++
+ #ifdef __i960__
+ #define _JBLEN 35
+ #endif
+
+In mini-os we use a dynamic reentrency buffer.
+
+Index: newlib/libc/include/sys/config.h
+===================================================================
+RCS file: /cvs/src/src/newlib/libc/include/sys/config.h,v
+retrieving revision 1.47
+diff -u -p -r1.47 config.h
+--- newlib/libc/include/sys/config.h   15 Mar 2007 21:32:12 -0000      1.47
++++ newlib/libc/include/sys/config.h   8 Nov 2007 16:32:44 -0000
+@@ -71,6 +71,10 @@
+ #endif
+ #endif
+ 
++#ifndef __DYNAMIC_REENT__
++#define __DYNAMIC_REENT__
++#endif
++
+ #ifdef __mn10200__
+ #define __SMALL_BITFIELDS
+ #endif
+
+Dynamic pointer to our reentrancy zone
+
+Index: newlib/libc/reent/getreent.c
+===================================================================
+RCS file: /cvs/src/src/newlib/libc/reent/getreent.c,v
+retrieving revision 1.2
+diff -u -p -r1.2 getreent.c
+--- newlib/libc/reent/getreent.c       7 Sep 2007 00:45:55 -0000       1.2
++++ newlib/libc/reent/getreent.c       8 Nov 2007 16:32:44 -0000
+@@ -3,12 +3,20 @@
+ #include <_ansi.h>
+ #include <reent.h>
+ 
++#define weak_alias(name, aliasname) \
++  extern __typeof (name) aliasname __attribute__ ((weak, alias (#name)));
++
+ #ifdef __getreent
+ #undef __getreent
+ #endif
++#ifdef __libc_getreent
++#undef __libc_getreent
++#endif
+ 
+ struct _reent *
+-_DEFUN_VOID(__getreent)
++__libc_getreent (void)
+ {
+   return _impure_ptr;
+ }
++weak_alias(__libc_getreent,__getreent)
++
+
+We can't provide a red zone in mini-os.
+
+Index: newlib/libc/machine/x86_64/memcpy.S
+===================================================================
+RCS file: /cvs/src/src/newlib/libc/machine/x86_64/memcpy.S,v
+retrieving revision 1.1
+diff -u -p -r1.1 memcpy.S
+--- newlib/libc/machine/x86_64/memcpy.S        28 Aug 2007 21:56:49 -0000      
1.1
++++ newlib/libc/machine/x86_64/memcpy.S        8 Nov 2007 16:32:44 -0000
+@@ -30,10 +30,18 @@ quadword_aligned:
+   cmpq    $256, rdx
+   jb      quadword_copy
+ 
++#if 1
++  subq    $32, rsp
++  movq    rax, 24 (rsp)
++  movq    r12, 16 (rsp)
++  movq    r13, 8  (rsp)
++  movq    r14, 0  (rsp)
++#else
+   movq    rax, -8  (rsp)
+   movq    r12, -16 (rsp)
+   movq    r13, -24 (rsp)
+   movq    r14, -32 (rsp)
++#endif
+ 
+   movq    rdx, rcx                /* Copy 128 bytes at a time with minimum 
cache polution */
+   shrq    $7, rcx
+@@ -89,10 +97,18 @@ loop:
+   movq    rdx, rcx
+   andq    $127, rcx
+   rep     movsb
++#if 1
++  movq    24 (rsp), rax
++  movq    16 (rsp), r12
++  movq    8  (rsp), r13
++  movq    0  (rsp), r14
++  addq    $32, rsp
++#else
+   movq    -8  (rsp), rax
+   movq    -16 (rsp), r12
+   movq    -24 (rsp), r13
+   movq    -32 (rsp), r14
++#endif
+   ret
+ 
+ 
diff -r 7b0c0ab0566b stubdom/stubdom-dm
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/stubdom/stubdom-dm        Mon Feb 11 17:16:12 2008 +0000
@@ -0,0 +1,97 @@
+#!/bin/bash
+#
+# Copyright 2007-2008 Samuel Thibault <samuel.thibault@xxxxxxxxxxxxx>
+#
+# dm script around stubdomains.
+#
+
+# To fit xterms nicely
+height=339
+
+# Parse arguments
+
+domid=
+domname=
+vncviewer=0
+vncpid=
+while [ "$#" -gt 0 ];
+do
+    if [ "$#" -ge 2 ];
+    then
+       case "$1" in
+           -d) domid=$2; shift ;;
+           -domain-name) domname=$2; shift ;;
+           -vnc)
+               ip=${2%:*};
+               vnc_port=${2#*:};
+               shift
+               ;;
+       esac
+    fi
+    case "$1" in
+       -vncviewer) vncviewer=1 ;;
+    esac
+    shift
+done
+
+[ -z "$domid"   ] && ( echo "couldn't find domain ID" ; exit 1 )
+[ -z "$domname" ] && ( echo "couldn't find domain name" ; exit 1 )
+
+# Termination handler
+
+term() {
+    kill %1
+    (
+       [ -n "$vncpid" ] && kill -9 $vncpid
+       xm destroy stubdom-$domname
+       #xm destroy $domname
+    ) &
+    # We need to exit immediately so as to let xend do the commands above
+    exit 0
+}
+
+trap term SIGHUP
+
+############
+# stubdomain
+# Wait for any previous stubdom to terminate
+while xm list | grep stubdom-$domname
+do
+       sleep 1
+done
+
+creation="xm create -c stubdom-$domname target=$domid memory=32"
+
+(while true ; do sleep 60 ; done) | $creation &
+#xterm -geometry +0+0 -e /bin/sh -c "$creation ; echo ; echo press ENTER to 
shut down ; read" &
+consolepid=$!
+
+
+while ! vnc_port=`xenstore-read /local/domain/$domid/console/vnc-port`
+do
+        # Check that the stubdom job is still alive
+        kill -0 $consolepid || term
+       sleep 1
+done
+
+################
+# DEBUG: tcpdump
+#while ! stubdomid=`xm domid stubdom-$domname`
+#do
+#        sleep 1
+#done
+#xterm -geometry 160x25+0+$height -e /bin/sh -c "tcpdump -n -i 
vif$stubdomid.0" &
+#xterm -geometry 160x25+0+$((2 * $height)) -e /bin/sh -c "tcpdump -n -i 
vif$stubdomid.1" &
+
+###########
+# vncviewer
+if [ "$vncviewer" = 1 ]
+then
+    vncviewer $ip:$vnc_port &
+    vncpid=$!
+fi
+
+# wait for SIGHUP or stubdom termination
+wait $consolepid
+
+term
diff -r 7b0c0ab0566b tools/ioemu/Makefile.target
--- a/tools/ioemu/Makefile.target       Mon Feb 11 14:55:33 2008 +0000
+++ b/tools/ioemu/Makefile.target       Mon Feb 11 17:16:12 2008 +0000
@@ -15,7 +15,7 @@ endif
 endif
 TARGET_PATH=$(SRC_PATH)/target-$(TARGET_BASE_ARCH)$(TARGET_SUB)
 VPATH=$(SRC_PATH):$(TARGET_PATH):$(SRC_PATH)/hw:$(SRC_PATH)/audio
-CPPFLAGS=-I. -I.. -I$(TARGET_PATH) -I$(SRC_PATH)
+CPPFLAGS+=-I. -I.. -I$(TARGET_PATH) -I$(SRC_PATH)
 CPPFLAGS+= -I$(XEN_ROOT)/tools/libxc
 CPPFLAGS+= -I$(XEN_ROOT)/tools/xenstore
 CPPFLAGS+= -I$(XEN_ROOT)/tools/include
@@ -66,7 +66,11 @@ QEMU_SYSTEM=qemu-fast
 QEMU_SYSTEM=qemu-fast
 endif
 
+ifdef CONFIG_STUBDOM
+QEMU_SYSTEM=qemu.a
+else
 QEMU_SYSTEM=qemu-dm
+endif
 
 ifdef CONFIG_USER_ONLY
 PROGS=$(QEMU_USER)
@@ -345,14 +349,25 @@ VL_OBJS+=cutils.o
 VL_OBJS+=cutils.o
 VL_OBJS+=block.o block-raw.o
 VL_OBJS+=block-cow.o block-qcow.o aes.o block-vmdk.o block-cloop.o block-dmg.o 
block-bochs.o block-vpc.o block-vvfat.o block-qcow2.o
+ifdef CONFIG_STUBDOM
+VL_OBJS+=block-vbd.o
+endif
 ifdef CONFIG_WIN32
 VL_OBJS+=tap-win32.o
 endif
 
-ifeq (,$(wildcard /usr/include/pci))
+ifdef CONFIG_STUBDOM
+CONFIG_PASSTHROUGH=1
+else
+  ifeq (,$(wildcard /usr/include/pci))
 $(warning *** pciutils-devl package not found - missing /usr/include/pci)
 $(warning *** PCI passthrough capability has been disabled)
-else
+  else
+CONFIG_PASSTHROUGH=1
+  endif
+endif
+
+ifdef CONFIG_PASSTHROUGH
 LIBS+=-lpci
 VL_OBJS+= pass-through.o
 CFLAGS += -DCONFIG_PASSTHROUGH
@@ -404,13 +419,13 @@ VL_OBJS+= ne2000.o rtl8139.o pcnet.o e10
 
 ifeq ($(TARGET_BASE_ARCH), i386)
 # Hardware support
-VL_OBJS+= ide.o pckbd.o ps2.o vga.o $(SOUND_HW) dma.o $(AUDIODRV) extboot.o
+VL_OBJS+= ide.o pckbd.o ps2.o vga.o dma.o extboot.o
 ifeq ($(ARCH),ia64)
 VL_OBJS+= fdc.o mc146818rtc.o serial.o pc.o
 else
 VL_OBJS+= fdc.o serial.o pc.o
 endif
-VL_OBJS+= cirrus_vga.o mixeng.o parallel.o acpi.o
+VL_OBJS+= cirrus_vga.o parallel.o acpi.o
 VL_OBJS+= usb-uhci.o smbus_eeprom.o
 VL_OBJS+= piix4acpi.o
 VL_OBJS+= xenstore.o
@@ -419,22 +434,31 @@ VL_OBJS+= xen_machine_pv.o
 VL_OBJS+= xen_machine_pv.o
 VL_OBJS+= xenfb.o
 VL_OBJS+= xen_console.o
+ifndef CONFIG_STUBDOM
 VL_OBJS+= tpm_tis.o
+VL_OBJS+= $(SOUND_HW) $(AUDIODRV) mixeng.o 
 CPPFLAGS += -DHAS_TPM
 CPPFLAGS += -DHAS_AUDIO
 endif
+endif
 ifeq ($(TARGET_BASE_ARCH), ppc)
-VL_OBJS+= ppc.o ide.o pckbd.o ps2.o vga.o $(SOUND_HW) dma.o $(AUDIODRV)
+VL_OBJS+= ppc.o ide.o pckbd.o ps2.o vga.o dma.o
 VL_OBJS+= mc146818rtc.o serial.o i8259.o i8254.o fdc.o m48t59.o
 VL_OBJS+= ppc_prep.o ppc_chrp.o cuda.o adb.o openpic.o heathrow_pic.o mixeng.o
 VL_OBJS+= grackle_pci.o prep_pci.o unin_pci.o
+ifndef CONFIG_STUBDOM
+VL_OBJS+= $(SOUND_HW) $(AUDIODRV) 
 CPPFLAGS += -DHAS_AUDIO
+endif
 endif
 ifeq ($(TARGET_ARCH), mips)
 VL_OBJS+= mips_r4k.o mips_malta.o mips_timer.o mips_int.o dma.o vga.o serial.o 
i8254.o i8259.o
 VL_OBJS+= ide.o gt64xxx.o pckbd.o ps2.o fdc.o mc146818rtc.o usb-uhci.o acpi.o
-VL_OBJS+= piix_pci.o parallel.o mixeng.o cirrus_vga.o $(SOUND_HW) $(AUDIODRV)
+VL_OBJS+= piix_pci.o parallel.o mixeng.o cirrus_vga.o
+ifndef CONFIG_STUBDOM
+VL_OBJS+= $(SOUND_HW) $(AUDIODRV) 
 DEFINES += -DHAS_AUDIO
+endif
 endif
 ifeq ($(TARGET_BASE_ARCH), sparc)
 ifeq ($(TARGET_ARCH), sparc64)
@@ -513,7 +537,11 @@ endif
 endif
 
 $(QEMU_SYSTEM): $(VL_OBJS) libqemu.a
+ifdef CONFIG_STUBDOM
+       $(AR) rcs $@ $(VL_OBJS)
+else
        $(CC) $(VL_LDFLAGS) -o $@ $^ $(LIBS) $(SDL_LIBS) $(COCOA_LIBS) 
$(VL_LIBS)
+endif
 
 cocoa.o: cocoa.m
        $(CC) $(CFLAGS) $(CPPFLAGS) $(BASE_CFLAGS) -c -o $@ $<
diff -r 7b0c0ab0566b tools/ioemu/aes.c
--- a/tools/ioemu/aes.c Mon Feb 11 14:55:33 2008 +0000
+++ b/tools/ioemu/aes.c Mon Feb 11 17:16:12 2008 +0000
@@ -33,9 +33,11 @@
 #define NDEBUG
 #include <assert.h>
 
+#ifndef CONFIG_STUBDOM
 typedef uint32_t u32;
 typedef uint16_t u16;
 typedef uint8_t u8;
+#endif
 
 #define MAXKC   (256/32)
 #define MAXKB   (256/8)
diff -r 7b0c0ab0566b tools/ioemu/block-vbd.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/ioemu/block-vbd.c   Mon Feb 11 17:16:12 2008 +0000
@@ -0,0 +1,341 @@
+/*
+ * Block driver for Mini-os PV devices
+ * Based on block-raw.c
+ * 
+ * Copyright (c) 2006 Fabrice Bellard, 2007 Samuel Thibault
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to 
deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#include "vl.h"
+#include "block_int.h"
+#include <assert.h>
+#include <xenbus.h>
+#include <blkfront.h>
+#include <malloc.h>
+
+#define SECTOR_SIZE 512
+
+#ifndef QEMU_TOOL
+#include "exec-all.h"
+#endif
+
+#define DEBUG_BLOCK
+#ifdef  DEBUG_BLOCK
+#define DEBUG_BLOCK_PRINT( formatCstr, args... ) fprintf( logfile, formatCstr, 
##args ); fflush( logfile )
+#else
+#define DEBUG_BLOCK_PRINT( formatCstr, args... )
+#endif
+
+#define FTYPE_FILE   0
+#define FTYPE_CD     1
+#define FTYPE_FD     2
+
+typedef struct BDRVVbdState {
+    struct blkfront_dev *dev;
+    int fd;
+    int type;
+    int mode;
+    uint64_t sectors;
+    unsigned sector_size;
+    QEMU_LIST_ENTRY(BDRVVbdState) list;
+} BDRVVbdState;
+
+QEMU_LIST_HEAD(, BDRVVbdState) vbds;
+
+static int vbd_probe(const uint8_t *buf, int buf_size, const char *filename)
+{
+    char *value;
+    if (xenbus_read(XBT_NIL, filename, &value))
+       return 0;
+    free(value);
+    return 100;
+}
+
+static int vbd_open(BlockDriverState *bs, const char *filename, int flags)
+{
+    BDRVVbdState *s = bs->opaque;
+
+    //handy to test posix access
+    //return -EIO;
+
+    s->dev = init_blkfront((char *) filename, &s->sectors, &s->sector_size, 
&s->mode);
+
+    if (!s->dev)
+       return -EIO;
+
+    if (SECTOR_SIZE % s->sector_size) {
+       printf("sector size is %d, we only support sector sizes that divide 
%d\n", s->sector_size, SECTOR_SIZE);
+       return -EIO;
+    }
+
+    s->fd = blkfront_open(s->dev);
+
+    QEMU_LIST_INSERT_HEAD(&vbds, s, list);
+
+    return 0;
+}
+
+typedef struct VbdAIOCB {
+    BlockDriverAIOCB common;
+    struct blkfront_aiocb aiocb;
+} VbdAIOCB;
+
+void qemu_aio_init(void)
+{
+}
+
+void qemu_aio_poll(void)
+{
+    BDRVVbdState *s;
+    for (s = vbds.lh_first; s; s = s->list.le_next)
+       blkfront_aio_poll(s->dev);
+}
+
+/* Wait for all IO requests to complete.  */
+void qemu_aio_flush(void)
+{
+    BDRVVbdState *s;
+    for (s = vbds.lh_first; s; s = s->list.le_next)
+       blkfront_sync(s->dev);
+}
+
+void qemu_aio_wait_start(void)
+{
+}
+
+void qemu_aio_wait(void)
+{
+    int some = 0;
+    DEFINE_WAIT(w);
+    while (1) {
+       BDRVVbdState *s;
+       add_waiter(w, blkfront_queue);
+        for (s = vbds.lh_first; s; s = s->list.le_next)
+           if (blkfront_aio_poll(s->dev))
+               some = 1;
+       if (some)
+           break;
+       schedule();
+    }
+    remove_waiter(w);
+}
+
+void qemu_aio_wait_end(void)
+{
+}
+
+static void vbd_aio_callback(struct blkfront_aiocb *aiocbp, int ret) {
+    VbdAIOCB *acb = aiocbp->data;
+
+    acb->common.cb(acb->common.opaque, ret);
+    qemu_aio_release(acb);
+}
+
+static VbdAIOCB *vbd_aio_setup(BlockDriverState *bs,
+        int64_t sector_num, uint8_t *buf, int nb_sectors,
+        BlockDriverCompletionFunc *cb, void *opaque)
+{
+    BDRVVbdState *s = bs->opaque;
+    VbdAIOCB *acb;
+
+    acb = qemu_aio_get(bs, cb, opaque);
+    if (!acb)
+       return NULL;
+    acb->aiocb.aio_dev = s->dev;
+    acb->aiocb.aio_buf = buf;
+    acb->aiocb.aio_nbytes = nb_sectors * SECTOR_SIZE;
+    acb->aiocb.aio_offset = sector_num * SECTOR_SIZE;
+    acb->aiocb.aio_cb = vbd_aio_callback;
+    acb->aiocb.data = acb;
+
+    return acb;
+}
+
+static BlockDriverAIOCB *vbd_aio_read(BlockDriverState *bs,
+        int64_t sector_num, uint8_t *buf, int nb_sectors,
+        BlockDriverCompletionFunc *cb, void *opaque)
+{
+    VbdAIOCB *acb;
+
+    acb = vbd_aio_setup(bs, sector_num, buf, nb_sectors, cb, opaque);
+    if (!acb)
+       return NULL;
+    blkfront_aio(&acb->aiocb, 0);
+    return &acb->common;
+}
+
+static BlockDriverAIOCB *vbd_aio_write(BlockDriverState *bs,
+        int64_t sector_num, const uint8_t *buf, int nb_sectors,
+        BlockDriverCompletionFunc *cb, void *opaque)
+{
+    VbdAIOCB *acb;
+
+    acb = vbd_aio_setup(bs, sector_num, (uint8_t*) buf, nb_sectors, cb, 
opaque);
+    if (!acb)
+       return NULL;
+    blkfront_aio(&acb->aiocb, 1);
+    return &acb->common;
+}
+
+static void vbd_cb(void *data, int ret) {
+    int *result = data;
+    result[0] = 1;
+    result[1] = ret;
+}
+
+static int vbd_aligned_io(BlockDriverState *bs,
+       int64_t sector_num, uint8_t *buf, int nb_sectors, int write)
+{
+    VbdAIOCB *acb;
+    int result[2];
+    result[0] = 0;
+    qemu_aio_wait_start();
+    acb = vbd_aio_setup(bs, sector_num, (uint8_t*) buf, nb_sectors, vbd_cb, 
&result);
+    blkfront_aio(&acb->aiocb, write);
+    while (!result[0])
+       qemu_aio_wait();
+    qemu_aio_wait_end();
+    return result[1];
+}
+
+static int vbd_read(BlockDriverState *bs,
+       int64_t sector_num, uint8_t *buf, int nb_sectors)
+{
+    uint8_t *iobuf;
+    int ret;
+    /* page alignment would be a bit better, but that's still fine compared to
+     * copying */
+    if (!((uintptr_t)buf & (SECTOR_SIZE-1)))
+       return vbd_aligned_io(bs, sector_num, buf, nb_sectors, 0);
+    iobuf = memalign(PAGE_SIZE, nb_sectors * SECTOR_SIZE);
+    ret = vbd_aligned_io(bs, sector_num, iobuf, nb_sectors, 0);
+    memcpy(buf, iobuf, nb_sectors * SECTOR_SIZE);
+    free(iobuf);
+    if (ret < 0)
+       return ret;
+    else if (ret != nb_sectors * SECTOR_SIZE)
+       return -EINVAL;
+    else
+       return 0;
+}
+
+static int vbd_write(BlockDriverState *bs,
+       int64_t sector_num, const uint8_t *buf, int nb_sectors)
+{
+    uint8_t *iobuf;
+    int ret;
+    if (!((uintptr_t)buf & (SECTOR_SIZE-1)))
+       return vbd_aligned_io(bs, sector_num, (uint8_t*) buf, nb_sectors, 1);
+    iobuf = memalign(PAGE_SIZE, nb_sectors * SECTOR_SIZE);
+    memcpy(iobuf, buf, nb_sectors * SECTOR_SIZE);
+    ret = vbd_aligned_io(bs, sector_num, iobuf, nb_sectors, 1);
+    free(iobuf);
+    if (ret < 0)
+       return ret;
+    else if (ret != nb_sectors * SECTOR_SIZE)
+       return -EINVAL;
+    else
+       return 0;
+}
+
+static void vbd_aio_cancel(BlockDriverAIOCB *blockacb)
+{
+    /* TODO */
+    //VbdAIOCB *acb = (VbdAIOCB *)blockacb;
+
+    // Try to cancel. If can't, wait for it, drop the callback and call 
qemu_aio_release(acb)
+}
+
+static void vbd_close(BlockDriverState *bs)
+{
+    BDRVVbdState *s = bs->opaque;
+    bs->total_sectors = 0;
+    if (s->fd >= 0) {
+        close(s->fd);
+        s->fd = -1;
+    }
+    QEMU_LIST_REMOVE(s, list);
+}
+
+static int64_t  vbd_getlength(BlockDriverState *bs)
+{
+    BDRVVbdState *s = bs->opaque;
+    return s->sectors * s->sector_size;
+}
+
+static void vbd_flush(BlockDriverState *bs)
+{
+    BDRVVbdState *s = bs->opaque;
+    blkfront_sync(s->dev);
+}
+
+/***********************************************/
+/* host device */
+
+static int vbd_is_inserted(BlockDriverState *bs)
+{
+    /* TODO: monitor the backend */
+    return 1;
+}
+
+/* currently only used by fdc.c, but a CD version would be good too */
+static int vbd_media_changed(BlockDriverState *bs)
+{
+    /* TODO: monitor the backend */
+    return -ENOTSUP;
+}
+
+static int vbd_eject(BlockDriverState *bs, int eject_flag)
+{
+    /* TODO: Xen support needed */
+    return -ENOTSUP;
+}
+
+static int vbd_set_locked(BlockDriverState *bs, int locked)
+{
+    /* TODO: Xen support needed */
+    return -ENOTSUP;
+}
+
+BlockDriver bdrv_vbd = {
+    "vbd",
+    sizeof(BDRVVbdState),
+    vbd_probe,
+    vbd_open,
+    NULL,
+    NULL,
+    vbd_close,
+    NULL,
+    vbd_flush,
+    
+    .bdrv_aio_read = vbd_aio_read,
+    .bdrv_aio_write = vbd_aio_write,
+    .bdrv_aio_cancel = vbd_aio_cancel,
+    .aiocb_size = sizeof(VbdAIOCB),
+    .bdrv_read = vbd_read,
+    .bdrv_write = vbd_write,
+    .bdrv_getlength = vbd_getlength,
+
+    /* removable device support */
+    .bdrv_is_inserted = vbd_is_inserted,
+    .bdrv_media_changed = vbd_media_changed,
+    .bdrv_eject = vbd_eject,
+    .bdrv_set_locked = vbd_set_locked,
+};
+
diff -r 7b0c0ab0566b tools/ioemu/block.c
--- a/tools/ioemu/block.c       Mon Feb 11 14:55:33 2008 +0000
+++ b/tools/ioemu/block.c       Mon Feb 11 17:16:12 2008 +0000
@@ -1235,6 +1235,9 @@ void bdrv_init(void)
 {
     bdrv_register(&bdrv_raw);
     bdrv_register(&bdrv_host_device);
+#ifdef CONFIG_STUBDOM
+    bdrv_register(&bdrv_vbd);
+#endif
 #ifndef _WIN32
     bdrv_register(&bdrv_cow);
 #endif
diff -r 7b0c0ab0566b tools/ioemu/configure
--- a/tools/ioemu/configure     Mon Feb 11 14:55:33 2008 +0000
+++ b/tools/ioemu/configure     Mon Feb 11 17:16:12 2008 +0000
@@ -74,6 +74,7 @@ linux_user="no"
 linux_user="no"
 darwin_user="no"
 build_docs="no"
+stubdom="no"
 uname_release=""
 
 # OS specific
@@ -230,6 +231,8 @@ for opt do
   --enable-darwin-user) darwin_user="yes"
   ;;
   --enable-uname-release=*) uname_release="$optarg"
+  ;;
+  --enable-stubdom) stubdom="yes"
   ;;
   esac
 done
@@ -416,7 +419,11 @@ if test -z "$target_list" ; then
         target_list="i386-darwin-user ppc-darwin-user $target_list"
     fi
 # the i386-dm target
-    target_list="i386-dm"
+    if test "$stubdom" = "yes"; then
+        target_list="i386-dm-stubdom"
+    else
+        target_list="i386-dm"
+    fi
 else
     target_list=`echo "$target_list" | sed -e 's/,/ /g'`
 fi
@@ -573,6 +580,11 @@ docdir="$prefix/share/doc/qemu"
 docdir="$prefix/share/doc/qemu"
 bindir="$prefix/$libdir/xen/bin"
 configdir="/etc/xen"
+fi
+
+if test "$stubdom" = "yes"; then
+    oss="no"
+    sdl="no"
 fi
 
 echo "Install prefix    $prefix"
@@ -943,6 +955,14 @@ if expr $target : '.*-dm' > /dev/null ; 
   echo "#define CONFIG_DM 1" >> $config_h
 fi
 
+if test "$stubdom" = "yes" ; then
+  echo "CONFIG_STUBDOM=yes" >> $config_mak
+  echo "#define CONFIG_STUBDOM 1" >> $config_h
+  echo "#define NO_UNIX_SOCKETS 1" >> $config_h
+  echo "#define NO_DAEMONIZE 1" >> $config_h
+  echo "#define NO_AIO 1" >> $config_h
+fi
+
 if test "$target_cpu" = "arm" -o "$target_cpu" = "armeb" -o "$target_cpu" = 
"sparc" -o "$target_cpu" = "sparc64" -o "$target_cpu" = "m68k"; then
   echo "CONFIG_SOFTFLOAT=yes" >> $config_mak
   echo "#define CONFIG_SOFTFLOAT 1" >> $config_h
diff -r 7b0c0ab0566b tools/ioemu/exec-all.h
--- a/tools/ioemu/exec-all.h    Mon Feb 11 14:55:33 2008 +0000
+++ b/tools/ioemu/exec-all.h    Mon Feb 11 17:16:12 2008 +0000
@@ -481,6 +481,9 @@ static inline int testandset (int *p)
 }
 #endif
 
+#ifdef CONFIG_STUBDOM
+#include <spinlock.h>
+#else
 typedef int spinlock_t;
 
 #define SPIN_LOCK_UNLOCKED 0
@@ -513,6 +516,7 @@ static inline int spin_trylock(spinlock_
 {
     return 1;
 }
+#endif
 #endif
 
 extern spinlock_t tb_lock;
diff -r 7b0c0ab0566b tools/ioemu/hw/ide.c
--- a/tools/ioemu/hw/ide.c      Mon Feb 11 14:55:33 2008 +0000
+++ b/tools/ioemu/hw/ide.c      Mon Feb 11 17:16:12 2008 +0000
@@ -22,6 +22,7 @@
  * THE SOFTWARE.
  */
 #include "vl.h"
+#include <malloc.h>
 
 /* debug IDE devices */
 //#define DEBUG_IDE
@@ -347,7 +348,7 @@ typedef struct IDEState {
     EndTransferFunc *end_transfer_func;
     uint8_t *data_ptr;
     uint8_t *data_end;
-    uint8_t io_buffer[MAX_MULT_SECTORS*512 + 4];
+    uint8_t *io_buffer;
     QEMUTimer *sector_write_timer; /* only used for win2k instal hack */
     uint32_t irq_count; /* counts IRQs when using win2k install hack */
 } IDEState;
@@ -2305,6 +2306,7 @@ static void ide_init2(IDEState *ide_stat
 
     for(i = 0; i < 2; i++) {
         s = ide_state + i;
+        s->io_buffer = memalign(PAGE_SIZE, MAX_MULT_SECTORS*512 + 4);
         if (i == 0)
             s->bs = hd0;
         else
diff -r 7b0c0ab0566b tools/ioemu/hw/scsi-disk.c
--- a/tools/ioemu/hw/scsi-disk.c        Mon Feb 11 14:55:33 2008 +0000
+++ b/tools/ioemu/hw/scsi-disk.c        Mon Feb 11 17:16:12 2008 +0000
@@ -26,13 +26,18 @@ do { fprintf(stderr, "scsi-disk: " fmt ,
 do { fprintf(stderr, "scsi-disk: " fmt , ##args); } while (0)
 
 #include "vl.h"
+#include <malloc.h>
 
 #define SENSE_NO_SENSE        0
 #define SENSE_NOT_READY       2
 #define SENSE_HARDWARE_ERROR  4
 #define SENSE_ILLEGAL_REQUEST 5
 
+#ifdef CONFIG_STUBDOM
+#define SCSI_DMA_BUF_SIZE    32768
+#else
 #define SCSI_DMA_BUF_SIZE    65536
+#endif
 
 typedef struct SCSIRequest {
     SCSIDevice *dev;
@@ -44,7 +49,7 @@ typedef struct SCSIRequest {
     int sector_count;
     /* The amounnt of data in the buffer.  */
     int buf_len;
-    uint8_t dma_buf[SCSI_DMA_BUF_SIZE];
+    uint8_t *dma_buf;
     BlockDriverAIOCB *aiocb;
     struct SCSIRequest *next;
 } SCSIRequest;
@@ -76,6 +81,7 @@ static SCSIRequest *scsi_new_request(SCS
         free_requests = r->next;
     } else {
         r = qemu_malloc(sizeof(SCSIRequest));
+       r->dma_buf = memalign(PAGE_SIZE, SCSI_DMA_BUF_SIZE);
     }
     r->dev = s;
     r->tag = tag;
diff -r 7b0c0ab0566b tools/ioemu/hw/xen_machine_fv.c
--- a/tools/ioemu/hw/xen_machine_fv.c   Mon Feb 11 14:55:33 2008 +0000
+++ b/tools/ioemu/hw/xen_machine_fv.c   Mon Feb 11 17:16:12 2008 +0000
@@ -24,6 +24,9 @@
  */
 
 #include "vl.h"
+#ifdef CONFIG_STUBDOM
+#include <xenbus.h>
+#endif
 #include <xen/hvm/params.h>
 #include <sys/mman.h>
 
diff -r 7b0c0ab0566b tools/ioemu/vl.c
--- a/tools/ioemu/vl.c  Mon Feb 11 14:55:33 2008 +0000
+++ b/tools/ioemu/vl.c  Mon Feb 11 17:16:12 2008 +0000
@@ -36,22 +36,29 @@
 #include <sys/times.h>
 #include <sys/wait.h>
 #include <termios.h>
+#ifndef CONFIG_STUBDOM
 #include <sys/poll.h>
+#endif
 #include <sys/mman.h>
 #include <sys/ioctl.h>
 #include <sys/resource.h>
 #include <sys/socket.h>
 #include <netinet/in.h>
+#ifndef CONFIG_STUBDOM
 #include <net/if.h>
+#endif
 #if defined(__NetBSD__)
 #include <net/if_tap.h>
 #endif
 #if defined(__linux__) || defined(__Linux__)
 #include <linux/if_tun.h>
 #endif
+#ifndef CONFIG_STUBDOM
 #include <arpa/inet.h>
 #include <dirent.h>
+#endif
 #include <netdb.h>
+#ifndef CONFIG_STUBDOM
 #ifdef _BSD
 #include <sys/stat.h>
 #ifndef _BSD
@@ -68,6 +75,7 @@
 #endif
 #if defined(__sun__)
 #include <stropts.h>
+#endif
 #endif
 #endif
 
@@ -132,10 +140,9 @@
 #define MAX_IOPORTS 65536
 
 const char *bios_dir = CONFIG_QEMU_SHAREDIR;
-char phys_ram_file[1024];
-void *ioport_opaque[MAX_IOPORTS];
-IOPortReadFunc *ioport_read_table[3][MAX_IOPORTS];
-IOPortWriteFunc *ioport_write_table[3][MAX_IOPORTS];
+void **ioport_opaque;
+IOPortReadFunc *(*ioport_read_table)[MAX_IOPORTS];
+IOPortWriteFunc *(*ioport_write_table)[MAX_IOPORTS];
 /* Note: bs_table[MAX_DISKS] is a dummy block driver if none available
    to store the VM snapshots */
 BlockDriverState *bs_table[MAX_DISKS + MAX_SCSI_DISKS + 1], *fd_table[MAX_FD];
@@ -270,6 +277,9 @@ void default_ioport_writel(void *opaque,
 
 void init_ioports(void)
 {
+    ioport_opaque = malloc(MAX_IOPORTS * sizeof(*ioport_opaque));
+    ioport_read_table = malloc(3 * MAX_IOPORTS * sizeof(**ioport_read_table));
+    ioport_write_table = malloc(3 * MAX_IOPORTS * 
sizeof(**ioport_write_table));
 }
 
 /* size is the word size in byte */
@@ -797,9 +807,6 @@ static MMRESULT timerID;
 static MMRESULT timerID;
 static HANDLE host_alarm = NULL;
 static unsigned int period = 1;
-#else
-/* frequency of the times() clock tick */
-static int timer_freq;
 #endif
 
 QEMUClock *qemu_new_clock(int type)
@@ -1137,9 +1144,6 @@ static void init_timer_alarm(void)
         struct itimerval itv;
 #endif
         
-        /* get times() syscall frequency */
-        timer_freq = sysconf(_SC_CLK_TCK);
-        
 #ifndef CONFIG_DM
         /* timer signal */
         sigfillset(&act.sa_mask);
@@ -1497,6 +1501,7 @@ static CharDriverState *qemu_chr_open_fi
     return qemu_chr_open_fd(-1, fd_out);
 }
 
+#ifndef CONFIG_STUBDOM
 static CharDriverState *qemu_chr_open_pipe(const char *filename)
 {
     int fd_in, fd_out;
@@ -1742,6 +1747,7 @@ static CharDriverState *qemu_chr_open_st
     }
     return chr;
 }
+#endif
 
 /*
  * Create a store entry for a device (e.g., monitor, serial/parallel lines).
@@ -1751,6 +1757,9 @@ static int store_dev_info(char *devName,
 static int store_dev_info(char *devName, int domid,
                           CharDriverState *cState, char *storeString)
 {
+#ifdef CONFIG_STUBDOM
+    return 0;
+#else
     int xc_handle;
     struct xs_handle *xs;
     char *path;
@@ -1826,8 +1835,10 @@ static int store_dev_info(char *devName,
     close(xc_handle);
 
     return 0;
-}
-
+#endif
+}
+
+#ifndef CONFIG_STUBDOM
 #ifdef __sun__
 /* Once Solaris has openpty(), this is going to be removed. */
 int openpty(int *amaster, int *aslave, char *name,
@@ -2486,6 +2497,7 @@ static CharDriverState *qemu_chr_open_wi
     return qemu_chr_open_win_file(fd_out);
 }
 #endif
+#endif
 
 /***********************************************************/
 /* UDP Net console */
@@ -2978,12 +2990,14 @@ CharDriverState *qemu_chr_open(const cha
        return qemu_chr_open_tcp(p, 0, 1);
     } else if (strstart(filename, "file:", &p)) {
         return qemu_chr_open_file_out(p);
+#ifndef CONFIG_STUBDOM
     } else if (strstart(filename, "pipe:", &p)) {
         return qemu_chr_open_pipe(p);
     } else if (!strcmp(filename, "pty")) {
         return qemu_chr_open_pty();
     } else if (!strcmp(filename, "stdio")) {
         return qemu_chr_open_stdio();
+#endif
     } else 
 #endif
 #if defined(__linux__)
@@ -3473,7 +3487,16 @@ static TAPState *net_tap_fd_init(VLANSta
     return s;
 }
 
-#ifdef _BSD
+#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);
+}
+#elif defined(_BSD)
 static int tap_open(char *ifname, int ifname_size)
 {
     int fd;
@@ -3561,6 +3584,7 @@ static int net_tap_init(VLANState *vlan,
     if (fd < 0)
         return -1;
 
+#ifndef CONFIG_STUBDOM
     if (!setup_script || !strcmp(setup_script, "no"))
         setup_script = "";
     if (setup_script[0] != '\0') {
@@ -3593,6 +3617,7 @@ static int net_tap_init(VLANState *vlan,
             }
         }
     }
+#endif
     s = net_tap_fd_init(vlan, fd);
     if (!s)
         return -1;
@@ -7041,12 +7066,14 @@ int main(int argc, char **argv)
     char usb_devices[MAX_USB_CMDLINE][128];
     int usb_devices_index;
     int fds[2];
+#ifndef CONFIG_STUBDOM
     struct rlimit rl;
+#endif
     sigset_t set;
     char qemu_dm_logfilename[128];
     const char *direct_pci = NULL;
 
-#ifndef __sun__
+#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)");
@@ -7072,6 +7099,7 @@ int main(int argc, char **argv)
        perror("setrlimit(RLIMIT_MEMLOCK)");
 #endif
 
+#ifndef CONFIG_STUBDOM
     /* Ensure that SIGUSR2 is blocked by default when a new thread is created,
        then only the threads that use the signal unblock it -- this fixes a
        race condition in Qcow support where the AIO signal is misdelivered.  */
@@ -7113,6 +7141,7 @@ int main(int argc, char **argv)
             }
         }
     }
+#endif
 #endif
 
     register_machines();
@@ -7631,7 +7660,15 @@ int main(int argc, char **argv)
 #ifdef CONFIG_DM
     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\n", msg);
+    else
+        xenstore_parse_domain_config(atoi(domid_s));
+#else /* CONFIG_STUBDOM */
     xenstore_parse_domain_config(domid);
+#endif /* CONFIG_STUBDOM */
 #endif /* CONFIG_DM */
 
 #ifdef USE_KQEMU
@@ -7799,8 +7836,10 @@ int main(int argc, char **argv)
        vnc_display_password(ds, password);
        if ((vnc_display_port = vnc_display_open(ds, vnc_display, vncunused)) < 
0) 
            exit (0);
+#ifndef CONFIG_STUBDOM     
        if (vncviewer)
            vnc_start_viewer(vnc_display_port);
+#endif
        xenstore_write_vncport(vnc_display_port);
     } else {
 #if defined(CONFIG_SDL)
@@ -7928,11 +7967,15 @@ int main(int argc, char **argv)
     }
 #endif
 
-    /* Unblock SIGTERM, which may have been blocked by the caller */
+#ifndef CONFIG_STUBDOM
+    /* Unblock SIGTERM and SIGHUP, which may have been blocked by the caller */
+    signal(SIGHUP, SIG_DFL);
     sigemptyset(&set);
     sigaddset(&set, SIGTERM);
+    sigaddset(&set, SIGHUP);
     if (sigprocmask(SIG_UNBLOCK, &set, NULL) == -1)
-        fprintf(stderr, "Failed to unblock SIGTERM\n");
+        fprintf(stderr, "Failed to unblock SIGTERM and SIGHUP\n");
+#endif
 
     main_loop();
     quit_timers();
diff -r 7b0c0ab0566b tools/ioemu/vl.h
--- a/tools/ioemu/vl.h  Mon Feb 11 14:55:33 2008 +0000
+++ b/tools/ioemu/vl.h  Mon Feb 11 17:16:12 2008 +0000
@@ -574,6 +574,9 @@ typedef struct BlockDriver BlockDriver;
 
 extern BlockDriver bdrv_raw;
 extern BlockDriver bdrv_host_device;
+#ifdef CONFIG_STUBDOM
+extern BlockDriver bdrv_vbd;
+#endif
 extern BlockDriver bdrv_cow;
 extern BlockDriver bdrv_qcow;
 extern BlockDriver bdrv_vmdk;
diff -r 7b0c0ab0566b tools/ioemu/vnc.c
--- a/tools/ioemu/vnc.c Mon Feb 11 14:55:33 2008 +0000
+++ b/tools/ioemu/vnc.c Mon Feb 11 17:16:12 2008 +0000
@@ -27,10 +27,12 @@
 #include <sys/stat.h>
 #include <sys/socket.h>
 #include <netinet/in.h>
-#include <arpa/inet.h>
 #include "vl.h"
 #include "qemu_socket.h"
 #include <assert.h>
+#ifdef CONFIG_STUBDOM
+#include <netfront.h>
+#endif
 
 /* The refresh interval starts at BASE.  If we scan the buffer and
    find no change, we increase by INC, up to MAX.  If the mouse moves
@@ -2407,7 +2409,9 @@ int vnc_display_open(DisplayState *ds, c
 #ifndef NO_UNIX_SOCKETS
     struct sockaddr_un uaddr;
 #endif
+#ifndef CONFIG_STUBDOM
     int reuse_addr, ret;
+#endif
     socklen_t addrlen;
     const char *p;
     VncState *vs = ds ? (VncState *)ds->opaque : vnc_state;
@@ -2539,6 +2543,15 @@ int vnc_display_open(DisplayState *ds, c
            return -1;
        }
 
+#ifdef CONFIG_STUBDOM
+        {
+            struct ip_addr ipaddr = { iaddr.sin_addr.s_addr };
+            struct ip_addr netmask = { 0 };
+            struct ip_addr gw = { 0 };
+            networking_set_addr(&ipaddr, &netmask, &gw);
+        }
+#endif
+
        iaddr.sin_port = htons(ntohs(iaddr.sin_port) + 5900);
 
        vs->lsock = socket(PF_INET, SOCK_STREAM, 0);
@@ -2549,6 +2562,7 @@ int vnc_display_open(DisplayState *ds, c
            return -1;
        }
 
+#ifndef CONFIG_STUBDOM
        reuse_addr = 1;
        ret = setsockopt(vs->lsock, SOL_SOCKET, SO_REUSEADDR,
                         (const char *)&reuse_addr, sizeof(reuse_addr));
@@ -2560,6 +2574,7 @@ int vnc_display_open(DisplayState *ds, c
            vs->display = NULL;
            return -1;
        }
+#endif
     }
 
     while (bind(vs->lsock, addr, addrlen) == -1) {
@@ -2590,6 +2605,7 @@ int vnc_display_open(DisplayState *ds, c
     return ntohs(iaddr.sin_port);
 }
 
+#ifndef CONFIG_STUBDOM
 int vnc_start_viewer(int port)
 {
     int pid, i, open_max;
@@ -2617,4 +2633,5 @@ int vnc_start_viewer(int port)
        return pid;
     }
 }
+#endif
 
diff -r 7b0c0ab0566b tools/ioemu/xenstore.c
--- a/tools/ioemu/xenstore.c    Mon Feb 11 14:55:33 2008 +0000
+++ b/tools/ioemu/xenstore.c    Mon Feb 11 17:16:12 2008 +0000
@@ -11,8 +11,10 @@
 #include "vl.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>
@@ -219,10 +221,18 @@ void xenstore_parse_domain_config(int do
         }
 
         /* open device now if media present */
+#ifdef CONFIG_STUBDOM
+        if (pasprintf(&buf, "%s/device/vbd/%s", path, e[i]) == -1)
+            continue;
+       if (bdrv_open2(bs, buf, 0 /* snapshot */, &bdrv_vbd) == 0) {
+           pstrcpy(bs->filename, sizeof(bs->filename), params);
+           continue;
+       }
+#endif
+
         if (params[0]) {
             if (bdrv_open(bs, params, 0 /* snapshot */) < 0)
-                fprintf(stderr, "qemu: could not open hard disk image '%s'\n",
-                        params);
+                fprintf(stderr, "qemu: could not open vbd '%s' or hard disk 
image '%s'\n", buf, params);
         }
     }
 
@@ -265,6 +275,10 @@ extern int vga_ram_size, bios_size;
 
 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;
@@ -367,6 +381,7 @@ void xenstore_process_logdirty_event(voi
     /* Ack that we've switched */
     xs_write(xsh, XBT_NULL, active_path, act, len);
     free(act);
+#endif
 }
 
 
diff -r 7b0c0ab0566b tools/libxc/Makefile
--- a/tools/libxc/Makefile      Mon Feb 11 14:55:33 2008 +0000
+++ b/tools/libxc/Makefile      Mon Feb 11 17:16:12 2008 +0000
@@ -5,10 +5,12 @@ MINOR    = 0
 MINOR    = 0
 
 CTRL_SRCS-y       :=
+ifneq ($(stubdom),y)
 CTRL_SRCS-y       += xc_core.c
 CTRL_SRCS-$(CONFIG_X86) += xc_core_x86.c
 CTRL_SRCS-$(CONFIG_IA64) += xc_core_ia64.c
 CTRL_SRCS-$(CONFIG_POWERPC) += xc_core_powerpc.c
+endif
 CTRL_SRCS-y       += xc_domain.c
 CTRL_SRCS-y       += xc_evtchn.c
 CTRL_SRCS-y       += xc_misc.c
@@ -19,21 +21,29 @@ CTRL_SRCS-y       += xc_sedf.c
 CTRL_SRCS-y       += xc_sedf.c
 CTRL_SRCS-y       += xc_csched.c
 CTRL_SRCS-y       += xc_tbuf.c
+ifneq ($(stubdom),y)
 CTRL_SRCS-y       += xc_resume.c
+endif
 CTRL_SRCS-$(CONFIG_X86) += xc_pagetab.c
+ifneq ($(stubdom),y)
 CTRL_SRCS-$(CONFIG_Linux) += xc_linux.c
 CTRL_SRCS-$(CONFIG_SunOS) += xc_solaris.c
 CTRL_SRCS-$(CONFIG_X86_Linux) += xc_ptrace.c xc_ptrace_core.c
 CTRL_SRCS-$(CONFIG_NetBSD) += xc_netbsd.c
+endif
+CTRL_SRCS-$(stubdom) += xc_minios.c
 
 GUEST_SRCS-y :=
 GUEST_SRCS-y += xg_private.c
+ifneq ($(stubdom),y)
 GUEST_SRCS-$(CONFIG_MIGRATE) += xc_domain_restore.c xc_domain_save.c
 GUEST_SRCS-$(CONFIG_HVM) += xc_hvm_build.c
+endif
 
 VPATH = ../../xen/common/libelf
 CFLAGS += -I../../xen/common/libelf
 
+ifneq ($(stubdom),y)
 GUEST_SRCS-y += libelf-tools.c libelf-loader.c
 GUEST_SRCS-y += libelf-dominfo.c libelf-relocate.c
 
@@ -46,6 +56,7 @@ GUEST_SRCS-$(CONFIG_X86)     += xc_dom_x
 GUEST_SRCS-$(CONFIG_X86)     += xc_dom_x86.c
 GUEST_SRCS-$(CONFIG_IA64)    += xc_dom_ia64.c
 GUEST_SRCS-$(CONFIG_POWERPC) += xc_dom_powerpc.c
+endif
 
 -include $(XEN_TARGET_ARCH)/Makefile
 
@@ -64,6 +75,10 @@ LDFLAGS  += -L.
 LDFLAGS  += -L.
 DEPS     = .*.d
 
+ifneq ($(stubdom),y)
+LDLIBS   = -lpthread
+endif
+
 CTRL_LIB_OBJS := $(patsubst %.c,%.o,$(CTRL_SRCS-y))
 CTRL_PIC_OBJS := $(patsubst %.c,%.opic,$(CTRL_SRCS-y))
 
@@ -71,10 +86,14 @@ GUEST_PIC_OBJS := $(patsubst %.c,%.opic,
 GUEST_PIC_OBJS := $(patsubst %.c,%.opic,$(GUEST_SRCS-y))
 
 LIB := libxenctrl.a
+ifneq ($(stubdom),y)
 LIB += libxenctrl.so libxenctrl.so.$(MAJOR) libxenctrl.so.$(MAJOR).$(MINOR)
+endif
 
 LIB += libxenguest.a
+ifneq ($(stubdom),y)
 LIB += libxenguest.so libxenguest.so.$(MAJOR) libxenguest.so.$(MAJOR).$(MINOR)
+endif
 
 .PHONY: all
 all: build
@@ -133,7 +152,7 @@ libxenctrl.so.$(MAJOR): libxenctrl.so.$(
        ln -sf $< $@
 
 libxenctrl.so.$(MAJOR).$(MINOR): $(CTRL_PIC_OBJS)
-       $(CC) $(CFLAGS) $(LDFLAGS) -Wl,$(SONAME_LDFLAG) 
-Wl,libxenctrl.so.$(MAJOR) $(SHLIB_CFLAGS) -o $@ $^ -lpthread
+       $(CC) $(CFLAGS) $(LDFLAGS) -Wl,$(SONAME_LDFLAG) 
-Wl,libxenctrl.so.$(MAJOR) $(SHLIB_CFLAGS) -o $@ $^ $(LDLIBS)
 
 # libxenguest
 
@@ -146,7 +165,7 @@ libxenguest.so.$(MAJOR): libxenguest.so.
        ln -sf $< $@
 
 libxenguest.so.$(MAJOR).$(MINOR): $(GUEST_PIC_OBJS) libxenctrl.so
-       $(CC) $(CFLAGS) $(LDFLAGS) -Wl,$(SONAME_LDFLAG) 
-Wl,libxenguest.so.$(MAJOR) $(SHLIB_CFLAGS) -o $@ $(GUEST_PIC_OBJS) -lz 
-lxenctrl -lpthread
+       $(CC) $(CFLAGS) $(LDFLAGS) -Wl,$(SONAME_LDFLAG) 
-Wl,libxenguest.so.$(MAJOR) $(SHLIB_CFLAGS) -o $@ $(GUEST_PIC_OBJS) -lz 
-lxenctrl $(LDLIBS)
 
 -include $(DEPS)
 
diff -r 7b0c0ab0566b tools/libxc/ia64/Makefile
--- a/tools/libxc/ia64/Makefile Mon Feb 11 14:55:33 2008 +0000
+++ b/tools/libxc/ia64/Makefile Mon Feb 11 17:16:12 2008 +0000
@@ -1,3 +1,4 @@ CTRL_SRCS-y += ia64/xc_ia64_stubs.c
+ifneq ($(stubdom),y)
 CTRL_SRCS-y += ia64/xc_ia64_stubs.c
 
 GUEST_SRCS-y += ia64/xc_ia64_hvm_build.c
@@ -8,6 +9,7 @@ GUEST_SRCS-y += ia64/dom_fw_acpi.c
 GUEST_SRCS-y += ia64/dom_fw_acpi.c
 
 DOMFW_SRCS_BASE := dom_fw_common.c dom_fw_domu.c dom_fw_asm.S
+endif
 DOMFW_SRCS := $(addprefix ia64/, $(DOMFW_SRCS_BASE))
 $(DOMFW_SRCS):
        ln -sf ../$(XEN_ROOT)/xen/arch/ia64/xen/$(@F) $@
diff -r 7b0c0ab0566b tools/libxc/xc_minios.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/libxc/xc_minios.c   Mon Feb 11 17:16:12 2008 +0000
@@ -0,0 +1,308 @@
+/******************************************************************************
+ *
+ * Copyright 2007-2008 Samuel Thibault <samuel.thibault@xxxxxxxxxxxxx>.
+ * All rights reserved.
+ * Use is subject to license terms.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, version 2 of the
+ * License.
+ */
+
+#undef NDEBUG
+#include "xc_private.h"
+#include <mm.h>
+#include <lib.h>
+#include <events.h>
+#include <wait.h>
+
+#include <xen/memory.h>
+#include <xen/sys/evtchn.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <assert.h>
+#include <stdint.h>
+#include <inttypes.h>
+
+extern struct wait_queue_head event_queue;
+
+int xc_interface_open(void)
+{
+    return 0;
+}
+
+int xc_interface_close(int xc_handle)
+{
+    return 0;
+}
+
+void *xc_map_foreign_batch(int xc_handle, uint32_t dom, int prot,
+                           xen_pfn_t *arr, int num)
+{
+    unsigned long pt_prot = 0;
+#ifdef __ia64__
+    /* TODO */
+#else
+    if (prot & PROT_READ)
+       pt_prot = L1_PROT_RO;
+    if (prot & PROT_WRITE)
+       pt_prot = L1_PROT;
+#endif
+    return map_frames_ex(arr, num, 1, 0, 1, dom, 1, pt_prot);
+}
+
+void *xc_map_foreign_range(int xc_handle, uint32_t dom,
+                           int size, int prot,
+                           unsigned long mfn)
+{
+    unsigned long pt_prot = 0;
+    printf("xc_map_foreign_range(%lx, %d)\n", mfn, size);
+#ifdef __ia64__
+    /* TODO */
+#else
+    if (prot & PROT_READ)
+       pt_prot = L1_PROT_RO;
+    if (prot & PROT_WRITE)
+       pt_prot = L1_PROT;
+#endif
+    assert(!(size % PAGE_SIZE));
+    return map_frames_ex(&mfn, size / PAGE_SIZE, 0, 1, 1, dom, 0, pt_prot);
+}
+
+int xc_map_foreign_ranges(int xc_handle, uint32_t dom,
+                          privcmd_mmap_entry_t *entries, int nr)
+{
+    printf("xc_map_foreign_ranges, TODO\n");
+    do_exit();
+}
+
+int do_xen_hypercall(int xc_handle, privcmd_hypercall_t *hypercall)
+{
+    multicall_entry_t call;
+    int i, ret;
+
+    call.op = hypercall->op;
+    for (i = 0; i < sizeof(hypercall->arg) / sizeof(*hypercall->arg); i++)
+       call.args[i] = hypercall->arg[i];
+
+    ret = HYPERVISOR_multicall(&call, 1);
+
+    if (ret < 0) {
+       errno = -ret;
+       return -1;
+    }
+    if (call.result < 0) {
+        errno = -call.result;
+        return -1;
+    }
+    return call.result;
+}
+
+int xc_find_device_number(const char *name)
+{
+    printf("xc_find_device_number(%s)\n", name);
+    do_exit();
+}
+
+int xc_evtchn_open(void)
+{
+    int fd = alloc_fd(FTYPE_EVTCHN), i;
+    for (i = 0; i < MAX_EVTCHN_PORTS; i++) {
+       files[fd].evtchn.ports[i].port = -1;
+        files[fd].evtchn.ports[i].bound = 0;
+    }
+    printf("evtchn_open() -> %d\n", fd);
+    return fd;
+}
+
+int xc_evtchn_close(int xce_handle)
+{
+    int i;
+    for (i = 0; i < MAX_EVTCHN_PORTS; i++)
+        if (files[xce_handle].evtchn.ports[i].bound)
+            unbind_evtchn(files[xce_handle].evtchn.ports[i].port);
+    files[xce_handle].type = FTYPE_NONE;
+    return 0;
+}
+
+int xc_evtchn_fd(int xce_handle)
+{
+    return xce_handle;
+}
+
+int xc_evtchn_notify(int xce_handle, evtchn_port_t port)
+{
+    int ret;
+
+    ret = notify_remote_via_evtchn(port);
+
+    if (ret < 0) {
+       errno = -ret;
+       ret = -1;
+    }
+    return ret;
+}
+
+/* XXX Note: This is not threadsafe */
+static int port_alloc(int xce_handle) {
+    int i;
+    for (i= 0; i < MAX_EVTCHN_PORTS; i++)
+       if (files[xce_handle].evtchn.ports[i].port == -1)
+           break;
+    if (i == MAX_EVTCHN_PORTS) {
+       printf("Too many ports in xc handle\n");
+       errno = EMFILE;
+       return -1;
+    }
+    files[xce_handle].evtchn.ports[i].pending = 0;
+    return i;
+}
+
+static void poke_port(int xce_handle, evtchn_port_t port)
+{
+    shared_info_t *s = HYPERVISOR_shared_info;
+    printk("poking port %d\n", port);
+    synch_set_bit(port, &s->evtchn_pending[0]);
+    xc_evtchn_unmask(xce_handle, port);
+}
+
+static void evtchn_handler(evtchn_port_t port, struct pt_regs *regs, void 
*data)
+{
+    int xce_handle = (intptr_t) data;
+    int i;
+    assert(files[xce_handle].type == FTYPE_EVTCHN);
+    mask_evtchn(port);
+    for (i= 0; i < MAX_EVTCHN_PORTS; i++)
+       if (files[xce_handle].evtchn.ports[i].port == port)
+           break;
+    if (i == MAX_EVTCHN_PORTS) {
+       printk("Unknown port for handle %d\n", xce_handle);
+       return;
+    }
+    files[xce_handle].evtchn.ports[i].pending++;
+    files[xce_handle].read = 1;
+    wake_up(&event_queue);
+}
+
+evtchn_port_or_error_t xc_evtchn_bind_unbound_port(int xce_handle, int domid)
+{
+    int ret, i;
+    evtchn_port_t port;
+
+    assert(get_current() == main_thread);
+    i = port_alloc(xce_handle);
+    if (i == -1)
+       return -1;
+
+    printf("xc_evtchn_bind_unbound_port(%d)", domid);
+    ret = evtchn_alloc_unbound(domid, evtchn_handler, 
(void*)(intptr_t)xce_handle, &port);
+    printf(" = %d\n", ret);
+
+    if (ret < 0) {
+       errno = -ret;
+       return -1;
+    }
+    files[xce_handle].evtchn.ports[i].bound = 1;
+    files[xce_handle].evtchn.ports[i].port = port;
+    return port;
+}
+
+evtchn_port_or_error_t xc_evtchn_bind_interdomain(int xce_handle, int domid,
+    evtchn_port_t remote_port)
+{
+    evtchn_port_t local_port;
+    int ret, i;
+
+    assert(get_current() == main_thread);
+    i = port_alloc(xce_handle);
+    if (i == -1)
+       return -1;
+
+    printf("xc_evtchn_bind_interdomain(%d, %"PRId32")", domid, remote_port);
+    ret = evtchn_bind_interdomain(domid, remote_port, evtchn_handler, 
(void*)(intptr_t)xce_handle, &local_port);
+    printf(" = %d\n", ret);
+
+    if (ret < 0) {
+       errno = -ret;
+       return -1;
+    }
+    files[xce_handle].evtchn.ports[i].bound = 1;
+    files[xce_handle].evtchn.ports[i].port = local_port;
+/* Poke port on start: HVM won't send an event for the very first request since
+ * we were not ready yet */
+    poke_port(xce_handle, local_port);
+    return local_port;
+}
+
+int xc_evtchn_unbind(int xce_handle, evtchn_port_t port)
+{
+    int i;
+    for (i = 0; i < MAX_EVTCHN_PORTS; i++)
+       if (files[xce_handle].evtchn.ports[i].port == port) {
+           files[xce_handle].evtchn.ports[i].port = -1;
+           break;
+       }
+    if (i == MAX_EVTCHN_PORTS)
+       printf("Warning: couldn't find port %"PRId32" for xc handle %x\n", 
port, xce_handle);
+    files[xce_handle].evtchn.ports[i].bound = 0;
+    unbind_evtchn(port);
+    return 0;
+}
+
+evtchn_port_or_error_t xc_evtchn_bind_virq(int xce_handle, unsigned int virq)
+{
+    evtchn_port_t port;
+    int i;
+
+    assert(get_current() == main_thread);
+    i = port_alloc(xce_handle);
+    if (i == -1)
+       return -1;
+
+    printf("xc_evtchn_bind_virq(%d)", virq);
+    port = bind_virq(virq, evtchn_handler, (void*)(intptr_t)xce_handle);
+
+    if (port < 0) {
+       errno = -port;
+       return -1;
+    }
+    files[xce_handle].evtchn.ports[i].bound = 1;
+    files[xce_handle].evtchn.ports[i].port = port;
+    return port;
+}
+
+evtchn_port_or_error_t xc_evtchn_pending(int xce_handle)
+{
+    int i;
+    unsigned long flags;
+    local_irq_save(flags);
+    for (i = 0; i < MAX_EVTCHN_PORTS; i++) {
+       evtchn_port_t port = files[xce_handle].evtchn.ports[i].port;
+       if (port != -1 && files[xce_handle].evtchn.ports[i].pending) {
+           files[xce_handle].evtchn.ports[i].pending--;
+           local_irq_restore(flags);
+           return port;
+       }
+    }
+    files[xce_handle].read = 0;
+    local_irq_restore(flags);
+    return -1;
+}
+
+int xc_evtchn_unmask(int xce_handle, evtchn_port_t port)
+{
+    unmask_evtchn(port);
+    return 0;
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff -r 7b0c0ab0566b tools/libxc/xc_pagetab.c
--- a/tools/libxc/xc_pagetab.c  Mon Feb 11 14:55:33 2008 +0000
+++ b/tools/libxc/xc_pagetab.c  Mon Feb 11 17:16:12 2008 +0000
@@ -5,14 +5,20 @@
  */
 #include "xc_private.h"
 
+#ifdef CONFIG_STUBDOM
+#include <arch_mm.h>
+#endif
+
 #if defined(__i386__)
 
 #define L1_PAGETABLE_SHIFT_PAE 12
 #define L2_PAGETABLE_SHIFT_PAE 21
 #define L3_PAGETABLE_SHIFT_PAE 30
 
+#ifndef CONFIG_STUBDOM
 #define L1_PAGETABLE_SHIFT             12
 #define L2_PAGETABLE_SHIFT             22
+#endif
 
 #define L0_PAGETABLE_MASK_PAE  0x00000ffffffff000ULL
 #define L1_PAGETABLE_MASK_PAE  0x1ffULL
@@ -30,8 +36,10 @@
 #define L3_PAGETABLE_SHIFT_PAE 30
 #define L4_PAGETABLE_SHIFT_PAE 39
 
+#ifndef CONFIG_STUBDOM
 #define L1_PAGETABLE_SHIFT             L1_PAGETABLE_SHIFT_PAE
 #define L2_PAGETABLE_SHIFT             L2_PAGETABLE_SHIFT_PAE
+#endif
 
 #define L0_PAGETABLE_MASK_PAE  0x000ffffffffff000ULL
 #define L1_PAGETABLE_MASK_PAE  0x1ffULL
diff -r 7b0c0ab0566b tools/libxc/xc_private.h
--- a/tools/libxc/xc_private.h  Mon Feb 11 14:55:33 2008 +0000
+++ b/tools/libxc/xc_private.h  Mon Feb 11 17:16:12 2008 +0000
@@ -30,12 +30,16 @@
 #define DECLARE_SYSCTL struct xen_sysctl sysctl
 #endif
 
+#ifdef CONFIG_STUBDOM
+#include <os.h>
+#else
 #undef PAGE_SHIFT
 #undef PAGE_SIZE
 #undef PAGE_MASK
 #define PAGE_SHIFT              XC_PAGE_SHIFT
 #define PAGE_SIZE               (1UL << PAGE_SHIFT)
 #define PAGE_MASK               (~(PAGE_SIZE-1))
+#endif
 
 #define DEBUG    1
 #define INFO     1
diff -r 7b0c0ab0566b tools/libxc/xenctrl.h
--- a/tools/libxc/xenctrl.h     Mon Feb 11 14:55:33 2008 +0000
+++ b/tools/libxc/xenctrl.h     Mon Feb 11 17:16:12 2008 +0000
@@ -42,6 +42,8 @@
  *  DEFINITIONS FOR CPU BARRIERS
  */
 
+#ifndef __barriers_defined
+#define __barriers_defined
 #if defined(__i386__)
 #define mb()  __asm__ __volatile__ ( "lock; addl $0,0(%%esp)" : : : "memory" )
 #define rmb() __asm__ __volatile__ ( "lock; addl $0,0(%%esp)" : : : "memory" )
@@ -61,6 +63,7 @@
 #define wmb()  __asm__ __volatile__ ("sync" : : : "memory") /* eieio? */
 #else
 #error "Define barriers"
+#endif
 #endif
 
 /*
diff -r 7b0c0ab0566b tools/libxc/xg_private.h
--- a/tools/libxc/xg_private.h  Mon Feb 11 14:55:33 2008 +0000
+++ b/tools/libxc/xg_private.h  Mon Feb 11 17:16:12 2008 +0000
@@ -34,6 +34,9 @@ char *xc_inflate_buffer(const char *in_b
 
 unsigned long csum_page (void * page);
 
+#ifdef CONFIG_STUBDOM
+#include <os.h>
+#else
 #define _PAGE_PRESENT   0x001
 #define _PAGE_RW        0x002
 #define _PAGE_USER      0x004
@@ -129,6 +132,7 @@ typedef l4_pgentry_64_t l4_pgentry_t;
 #define l3_table_offset(_a) l3_table_offset_x86_64(_a)
 #define l4_table_offset(_a) l4_table_offset_x86_64(_a)
 #endif
+#endif
 
 #define PAGE_SHIFT_X86          12
 #define PAGE_SIZE_X86           (1UL << PAGE_SHIFT_X86)
diff -r 7b0c0ab0566b tools/python/xen/xend/image.py
--- a/tools/python/xen/xend/image.py    Mon Feb 11 14:55:33 2008 +0000
+++ b/tools/python/xen/xend/image.py    Mon Feb 11 17:16:12 2008 +0000
@@ -335,11 +335,19 @@ class ImageHandler:
             return
         if self.pid:
             try:
-                os.kill(self.pid, signal.SIGKILL)
+                os.kill(self.pid, signal.SIGHUP)
             except OSError, exn:
                 log.exception(exn)
             try:
-                os.waitpid(self.pid, 0)
+                for i in xrange(10):
+                    (p, rv) = os.waitpid(self.pid, os.WNOHANG)
+                    log.debug("waitpid returned %s %s" % (p,rv))
+                    if p == self.pid:
+                        break
+                    time.sleep(1)
+                else:
+                    os.kill(self.pid, signal.SIGKILL)
+                    os.waitpid(self.pid, 0)
             except OSError, exn:
                 # This is expected if Xend has been restarted within the
                 # life of this domain.  In this case, we can kill the process,

_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel