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] [RFC2] Add stubdomain support

To: Keir Fraser <Keir.Fraser@xxxxxxxxxxxx>
Subject: [Xen-devel] [RFC2] Add stubdomain support
From: Samuel Thibault <samuel.thibault@xxxxxxxxxxxxx>
Date: Tue, 12 Feb 2008 14:04:47 +0000
Cc: xen-devel@xxxxxxxxxxxxxxxxxxx
Delivery-date: Tue, 12 Feb 2008 06:06:45 -0800
Envelope-to: www-data@xxxxxxxxxxxxxxxxxx
In-reply-to: <C3D66D59.13BE6%Keir.Fraser@xxxxxxxxxxxx>
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>, Keir Fraser <Keir.Fraser@xxxxxxxxxxxx>, xen-devel@xxxxxxxxxxxxxxxxxxx
References: <20080211192137.GB4483@implementation> <C3D66D59.13BE6%Keir.Fraser@xxxxxxxxxxxx>
Sender: xen-devel-bounces@xxxxxxxxxxxxxxxxxxx
User-agent: Mutt/1.5.12-2006-07-14
Keir Fraser, le Mon 11 Feb 2008 21:23:37 +0000, a écrit :
> perhaps it is more appropriate to clean up stubdom's -- it's private
> architectural definitions shouldn't be leaking into code that includes
> stubdom's public high-level headers.

Ok, actually I just had to move the actual definitions of PAGE_SIZE
and STACK_SIZE to a separate header, and that let me avoid pulling all
internal definitions.

BTW, one of the reason for not enabling its compilation by default could
at least be that since we need to setup a cross-compilation environment
(binutils, gcc, newlib), we have to download about 70MB of source...



Add stubdomain support.

- Move PAGE_SIZE and STACK_SIZE into __PAGE_SIZE and __STACK_SIZE in
  arch_limits.h so as to permit getting them from there without pulling all
  the internal Mini-OS defines.
- 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 88818d55e95a .hgignore
--- a/.hgignore Tue Feb 12 11:37:45 2008 +0000
+++ b/.hgignore Tue Feb 12 14:02:15 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 88818d55e95a Config.mk
--- a/Config.mk Tue Feb 12 11:37:45 2008 +0000
+++ b/Config.mk Tue Feb 12 14:02:15 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 88818d55e95a extras/mini-os/Config.mk
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/extras/mini-os/Config.mk  Tue Feb 12 14:02:15 2008 +0000
@@ -0,0 +1,76 @@
+# 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
+DEF_CPPFLAGS += -I$(XEN_ROOT)/tools/xenstore
+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 88818d55e95a extras/mini-os/Makefile
--- a/extras/mini-os/Makefile   Tue Feb 12 11:37:45 2008 +0000
+++ b/extras/mini-os/Makefile   Tue Feb 12 14:02:15 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 88818d55e95a extras/mini-os/arch/ia64/Makefile
--- a/extras/mini-os/arch/ia64/Makefile Tue Feb 12 11:37:45 2008 +0000
+++ b/extras/mini-os/arch/ia64/Makefile Tue Feb 12 14:02:15 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 88818d55e95a extras/mini-os/arch/ia64/minios-ia64.lds
--- a/extras/mini-os/arch/ia64/minios-ia64.lds  Tue Feb 12 11:37:45 2008 +0000
+++ b/extras/mini-os/arch/ia64/minios-ia64.lds  Tue Feb 12 14:02:15 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 88818d55e95a extras/mini-os/arch/ia64/mm.c
--- a/extras/mini-os/arch/ia64/mm.c     Tue Feb 12 11:37:45 2008 +0000
+++ b/extras/mini-os/arch/ia64/mm.c     Tue Feb 12 14:02:15 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 88818d55e95a extras/mini-os/arch/x86/Makefile
--- a/extras/mini-os/arch/x86/Makefile  Tue Feb 12 11:37:45 2008 +0000
+++ b/extras/mini-os/arch/x86/Makefile  Tue Feb 12 14:02:15 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 88818d55e95a extras/mini-os/arch/x86/arch.mk
--- a/extras/mini-os/arch/x86/arch.mk   Tue Feb 12 11:37:45 2008 +0000
+++ b/extras/mini-os/arch/x86/arch.mk   Tue Feb 12 14:02:15 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 88818d55e95a extras/mini-os/arch/x86/minios-x86_32.lds
--- a/extras/mini-os/arch/x86/minios-x86_32.lds Tue Feb 12 11:37:45 2008 +0000
+++ b/extras/mini-os/arch/x86/minios-x86_32.lds Tue Feb 12 14:02:15 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 88818d55e95a extras/mini-os/arch/x86/minios-x86_64.lds
--- a/extras/mini-os/arch/x86/minios-x86_64.lds Tue Feb 12 11:37:45 2008 +0000
+++ b/extras/mini-os/arch/x86/minios-x86_64.lds Tue Feb 12 14:02:15 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 88818d55e95a extras/mini-os/arch/x86/mm.c
--- a/extras/mini-os/arch/x86/mm.c      Tue Feb 12 11:37:45 2008 +0000
+++ b/extras/mini-os/arch/x86/mm.c      Tue Feb 12 14:02:15 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 88818d55e95a extras/mini-os/arch/x86/x86_32.S
--- a/extras/mini-os/arch/x86/x86_32.S  Tue Feb 12 11:37:45 2008 +0000
+++ b/extras/mini-os/arch/x86/x86_32.S  Tue Feb 12 14:02:15 2008 +0000
@@ -1,5 +1,5 @@
 #include <os.h>
-#include <arch_mm.h>
+#include <arch_limits.h>
 #include <xen/arch-x86_32.h>
 
 .section __xen_guest
@@ -22,12 +22,12 @@ _start:
 _start:
         cld
         lss stack_start,%esp
-        andl $(~(STACK_SIZE-1)), %esp
+        andl $(~(__STACK_SIZE-1)), %esp
         push %esi 
         call start_kernel
 
 stack_start:
-       .long stack+(2*STACK_SIZE), __KERNEL_SS
+       .long stack+(2*__STACK_SIZE), __KERNEL_SS
 
         /* Unpleasant -- the PTE that maps this page is actually overwritten */
         /* to map the real shared-info page! :-)                             */
diff -r 88818d55e95a extras/mini-os/arch/x86/x86_64.S
--- a/extras/mini-os/arch/x86/x86_64.S  Tue Feb 12 11:37:45 2008 +0000
+++ b/extras/mini-os/arch/x86/x86_64.S  Tue Feb 12 14:02:15 2008 +0000
@@ -1,5 +1,5 @@
 #include <os.h>
-#include <arch_mm.h>
+#include <arch_limits.h>
 #include <xen/features.h>
 
 .section __xen_guest
@@ -19,12 +19,12 @@ _start:
 _start:
         cld
         movq stack_start(%rip),%rsp
-        andq $(~(STACK_SIZE-1)), %rsp
+        andq $(~(__STACK_SIZE-1)), %rsp
         movq %rsi,%rdi
         call start_kernel
 
 stack_start:
-        .quad stack+(2*STACK_SIZE)
+        .quad stack+(2*__STACK_SIZE)
 
         /* Unpleasant -- the PTE that maps this page is actually overwritten */
         /* to map the real shared-info page! :-)                             */
diff -r 88818d55e95a extras/mini-os/blkfront.c
--- a/extras/mini-os/blkfront.c Tue Feb 12 11:37:45 2008 +0000
+++ b/extras/mini-os/blkfront.c Tue Feb 12 14:02:15 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 88818d55e95a extras/mini-os/include/arch/cc.h
--- a/extras/mini-os/include/arch/cc.h  Tue Feb 12 11:37:45 2008 +0000
+++ b/extras/mini-os/include/arch/cc.h  Tue Feb 12 14:02:15 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 88818d55e95a extras/mini-os/include/byteswap.h
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/extras/mini-os/include/byteswap.h Tue Feb 12 14:02:15 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 88818d55e95a extras/mini-os/include/console.h
--- a/extras/mini-os/include/console.h  Tue Feb 12 11:37:45 2008 +0000
+++ b/extras/mini-os/include/console.h  Tue Feb 12 14:02:15 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 88818d55e95a extras/mini-os/include/errno.h
--- a/extras/mini-os/include/errno.h    Tue Feb 12 11:37:45 2008 +0000
+++ b/extras/mini-os/include/errno.h    Tue Feb 12 14:02:15 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 88818d55e95a extras/mini-os/include/fcntl.h
--- a/extras/mini-os/include/fcntl.h    Tue Feb 12 11:37:45 2008 +0000
+++ b/extras/mini-os/include/fcntl.h    Tue Feb 12 14:02:15 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 88818d55e95a extras/mini-os/include/fs.h
--- a/extras/mini-os/include/fs.h       Tue Feb 12 11:37:45 2008 +0000
+++ b/extras/mini-os/include/fs.h       Tue Feb 12 14:02:15 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 88818d55e95a extras/mini-os/include/ia64/arch_limits.h
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/extras/mini-os/include/ia64/arch_limits.h Tue Feb 12 14:02:15 2008 +0000
@@ -0,0 +1,12 @@
+
+#ifndef __ARCH_LIMITS_H__
+#define __ARCH_LIMITS_H__
+
+/* Commonly 16K pages are used. */
+#define __PAGE_SHIFT   14      /* 16K pages */
+#define __PAGE_SIZE    (1<<(__PAGE_SHIFT))
+
+#define __STACK_SIZE_PAGE_ORDER   2
+#define __STACK_SIZE              (__PAGE_SIZE * (1 << 
__STACK_SIZE_PAGE_ORDER))
+          
+#endif /* __ARCH_LIMITS_H__ */
diff -r 88818d55e95a extras/mini-os/include/ia64/arch_mm.h
--- a/extras/mini-os/include/ia64/arch_mm.h     Tue Feb 12 11:37:45 2008 +0000
+++ b/extras/mini-os/include/ia64/arch_mm.h     Tue Feb 12 14:02:15 2008 +0000
@@ -35,11 +35,9 @@
 #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_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 88818d55e95a extras/mini-os/include/ia64/page.h
--- a/extras/mini-os/include/ia64/page.h        Tue Feb 12 11:37:45 2008 +0000
+++ b/extras/mini-os/include/ia64/page.h        Tue Feb 12 14:02:15 2008 +0000
@@ -43,9 +43,9 @@
 /* The efi-pal page size for text and data. */
 #define PAL_TR_PAGE_SIZE       PTE_PS_1M
 
-/* Commonly 16K pages are used. */
-#define PAGE_SHIFT     14      /* 16K pages */
-#define PAGE_SIZE      (1<<(PAGE_SHIFT))
+#include "arch_limits.h"
+#define PAGE_SHIFT     __PAGE_SHIFT
+#define PAGE_SIZE      __PAGE_SIZE
 #define PAGE_MASK      (~(PAGE_SIZE-1))
 
 #define KSTACK_PAGES   4       /* 4 pages for the kernel stack + bsp */
diff -r 88818d55e95a extras/mini-os/include/lib.h
--- a/extras/mini-os/include/lib.h      Tue Feb 12 11:37:45 2008 +0000
+++ b/extras/mini-os/include/lib.h      Tue Feb 12 14:02:15 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 88818d55e95a 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      Tue Feb 12 14:02:15 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 88818d55e95a extras/mini-os/include/mm.h
--- a/extras/mini-os/include/mm.h       Tue Feb 12 11:37:45 2008 +0000
+++ b/extras/mini-os/include/mm.h       Tue Feb 12 14:02:15 2008 +0000
@@ -36,7 +36,12 @@
 #endif
 
 #include <lib.h>
+
+#include <arch_limits.h>
 #include <arch_mm.h>
+
+#define STACK_SIZE_PAGE_ORDER __STACK_SIZE_PAGE_ORDER
+#define STACK_SIZE __STACK_SIZE
 
 
 void init_mm(void);
@@ -61,5 +66,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 88818d55e95a extras/mini-os/include/netfront.h
--- a/extras/mini-os/include/netfront.h Tue Feb 12 11:37:45 2008 +0000
+++ b/extras/mini-os/include/netfront.h Tue Feb 12 14:02:15 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 88818d55e95a 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     Tue Feb 12 14:02:15 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 88818d55e95a 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     Tue Feb 12 14:02:15 2008 +0000
@@ -0,0 +1,9 @@
+#ifndef _POSIX_LIMITS_H
+#define _POSIX_LIMITS_H
+
+#include_next <limits.h>
+#include <arch_limits.h>
+
+#define PATH_MAX __PAGE_SIZE
+
+#endif /* _POSIX_LIMITS_H */
diff -r 88818d55e95a 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      Tue Feb 12 14:02:15 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 88818d55e95a 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 Tue Feb 12 14:02:15 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 88818d55e95a 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        Tue Feb 12 14:02:15 
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 88818d55e95a 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    Tue Feb 12 14:02:15 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 88818d55e95a 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     Tue Feb 12 14:02:15 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 88818d55e95a 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    Tue Feb 12 14:02:15 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 88818d55e95a 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  Tue Feb 12 14:02:15 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 88818d55e95a 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   Tue Feb 12 14:02:15 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 88818d55e95a 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 Tue Feb 12 14:02:15 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 88818d55e95a 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 Tue Feb 12 14:02:15 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 88818d55e95a 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    Tue Feb 12 14:02:15 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 88818d55e95a 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       Tue Feb 12 14:02:15 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 88818d55e95a 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     Tue Feb 12 14:02:15 2008 +0000
@@ -0,0 +1,12 @@
+#ifndef _POSIX_UNISTD_H
+#define _POSIX_UNISTD_H
+
+#include_next <unistd.h>
+#include <sys/select.h>
+#include <arch_limits.h>
+
+#define getpagesize() __PAGE_SIZE
+
+int ftruncate(int fd, off_t length);
+
+#endif /* _POSIX_UNISTD_H */
diff -r 88818d55e95a extras/mini-os/include/sched.h
--- a/extras/mini-os/include/sched.h    Tue Feb 12 11:37:45 2008 +0000
+++ b/extras/mini-os/include/sched.h    Tue Feb 12 14:02:15 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 88818d55e95a extras/mini-os/include/sys/time.h
--- a/extras/mini-os/include/sys/time.h Tue Feb 12 11:37:45 2008 +0000
+++ b/extras/mini-os/include/sys/time.h Tue Feb 12 14:02:15 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 88818d55e95a extras/mini-os/include/time.h
--- a/extras/mini-os/include/time.h     Tue Feb 12 11:37:45 2008 +0000
+++ b/extras/mini-os/include/time.h     Tue Feb 12 14:02:15 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 88818d55e95a extras/mini-os/include/x86/arch_limits.h
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/extras/mini-os/include/x86/arch_limits.h  Tue Feb 12 14:02:15 2008 +0000
@@ -0,0 +1,20 @@
+
+#ifndef __ARCH_LIMITS_H__
+#define __ARCH_LIMITS_H__
+
+#define __PAGE_SHIFT      12
+
+#ifdef __ASSEMBLY__
+#define __PAGE_SIZE       (1 << __PAGE_SHIFT)
+#else
+#ifndef CONFIG_X86_PAE
+#define __PAGE_SIZE       (1UL << __PAGE_SHIFT)
+#else
+#define __PAGE_SIZE       (1ULL << __PAGE_SHIFT)
+#endif
+#endif
+
+#define __STACK_SIZE_PAGE_ORDER  4
+#define __STACK_SIZE             (__PAGE_SIZE * (1 << __STACK_SIZE_PAGE_ORDER))
+          
+#endif /* __ARCH_LIMITS_H__ */
diff -r 88818d55e95a extras/mini-os/include/x86/arch_mm.h
--- a/extras/mini-os/include/x86/arch_mm.h      Tue Feb 12 11:37:45 2008 +0000
+++ b/extras/mini-os/include/x86/arch_mm.h      Tue Feb 12 14:02:15 2008 +0000
@@ -157,16 +157,9 @@ typedef unsigned long pgentry_t;
 #define L4_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED|_PAGE_DIRTY|_PAGE_USER)
 #endif /* __i386__ || __x86_64__ */
 
-#ifdef __ASSEMBLY__
-#define PAGE_SIZE       (1 << L1_PAGETABLE_SHIFT)
-#else
-#ifndef CONFIG_X86_PAE
-#define PAGE_SIZE       (1UL << L1_PAGETABLE_SHIFT)
-#else
-#define PAGE_SIZE       (1ULL << L1_PAGETABLE_SHIFT)
-#endif
-#endif
-#define PAGE_SHIFT      L1_PAGETABLE_SHIFT
+#include "arch_limits.h"
+#define PAGE_SIZE       __PAGE_SIZE
+#define PAGE_SHIFT      __PAGE_SHIFT
 #define PAGE_MASK       (~(PAGE_SIZE-1))
 
 #define PFN_UP(x)      (((x) + PAGE_SIZE-1) >> L1_PAGETABLE_SHIFT)
@@ -176,9 +169,6 @@ 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_SIZE * (1 << STACK_SIZE_PAGE_ORDER))
 
 #ifndef __ASSEMBLY__
 /* Definitions for machine and pseudophysical addresses. */
@@ -257,5 +247,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 88818d55e95a extras/mini-os/include/x86/arch_sched.h
--- a/extras/mini-os/include/x86/arch_sched.h   Tue Feb 12 11:37:45 2008 +0000
+++ b/extras/mini-os/include/x86/arch_sched.h   Tue Feb 12 14:02:15 2008 +0000
@@ -2,7 +2,7 @@
 #ifndef __ARCH_SCHED_H__
 #define __ARCH_SCHED_H__
 
-#include <arch_mm.h>
+#include <arch_limits.h>
 
 static inline struct thread* get_current(void)
 {
@@ -12,7 +12,7 @@ static inline struct thread* get_current
 #else
     register unsigned long sp asm("rsp");
 #endif 
-    current = (void *)(unsigned long)(sp & ~(STACK_SIZE-1));
+    current = (void *)(unsigned long)(sp & ~(__STACK_SIZE-1));
     return *current;
 }
 
diff -r 88818d55e95a extras/mini-os/include/x86/arch_spinlock.h
--- a/extras/mini-os/include/x86/arch_spinlock.h        Tue Feb 12 11:37:45 
2008 +0000
+++ b/extras/mini-os/include/x86/arch_spinlock.h        Tue Feb 12 14:02:15 
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 88818d55e95a extras/mini-os/include/x86/os.h
--- a/extras/mini-os/include/x86/os.h   Tue Feb 12 11:37:45 2008 +0000
+++ b/extras/mini-os/include/x86/os.h   Tue Feb 12 14:02:15 2008 +0000
@@ -563,6 +563,7 @@ static __inline__ int synch_var_test_bit
  synch_var_test_bit((nr),(addr)))
 
 
+#undef ADDR
 
 #endif /* not assembly */
 #endif /* _OS_H_ */
diff -r 88818d55e95a extras/mini-os/lib/sys.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/extras/mini-os/lib/sys.c  Tue Feb 12 14:02:15 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 88818d55e95a extras/mini-os/lib/xs.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/extras/mini-os/lib/xs.c   Tue Feb 12 14:02:15 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 88818d55e95a extras/mini-os/main-caml.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/extras/mini-os/main-caml.c        Tue Feb 12 14:02:15 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 88818d55e95a extras/mini-os/main.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/extras/mini-os/main.c     Tue Feb 12 14:02:15 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 88818d55e95a extras/mini-os/minios.mk
--- a/extras/mini-os/minios.mk  Tue Feb 12 11:37:45 2008 +0000
+++ b/extras/mini-os/minios.mk  Tue Feb 12 14:02:15 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 88818d55e95a extras/mini-os/mm.c
--- a/extras/mini-os/mm.c       Tue Feb 12 11:37:45 2008 +0000
+++ b/extras/mini-os/mm.c       Tue Feb 12 14:02:15 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 88818d55e95a extras/mini-os/netfront.c
--- a/extras/mini-os/netfront.c Tue Feb 12 11:37:45 2008 +0000
+++ b/extras/mini-os/netfront.c Tue Feb 12 14:02:15 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 88818d55e95a extras/mini-os/sched.c
--- a/extras/mini-os/sched.c    Tue Feb 12 11:37:45 2008 +0000
+++ b/extras/mini-os/sched.c    Tue Feb 12 14:02:15 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 88818d55e95a stubdom/Makefile
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/stubdom/Makefile  Tue Feb 12 14:02:15 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:=i686
+endif
+
+ifeq ($(GNU_TARGET_ARCH), i686)
+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 -z 9 -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 88818d55e95a stubdom/README
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/stubdom/README    Tue Feb 12 14:02:15 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 88818d55e95a stubdom/binutils.patch
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/stubdom/binutils.patch    Tue Feb 12 14:02:15 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 88818d55e95a stubdom/caml/Makefile
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/stubdom/caml/Makefile     Tue Feb 12 14:02:15 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 88818d55e95a stubdom/caml/hello.ml
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/stubdom/caml/hello.ml     Tue Feb 12 14:02:15 2008 +0000
@@ -0,0 +1,4 @@
+let main arg =
+  Printf.printf "Hello, world!\n%!."
+
+let _ = Callback.register "main" main
diff -r 88818d55e95a stubdom/gcc.patch
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/stubdom/gcc.patch Tue Feb 12 14:02:15 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 88818d55e95a stubdom/libpci.config.h
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/stubdom/libpci.config.h   Tue Feb 12 14:02:15 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 88818d55e95a stubdom/libpci.config.mak
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/stubdom/libpci.config.mak Tue Feb 12 14:02:15 2008 +0000
@@ -0,0 +1,2 @@
+LIBZ=-lz
+LDLIBS+=$(LIBZ)
diff -r 88818d55e95a stubdom/newlib.patch
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/stubdom/newlib.patch      Tue Feb 12 14:02:15 2008 +0000
@@ -0,0 +1,203 @@
+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)
+
+We don't want u?int32_t to be long as our code assume in a lot of places to be
+int.
+
+Index: newlib/libc/include/stdint.h
+===================================================================
+RCS file: /cvs/src/src/newlib/libc/include/stdint.h,v
+retrieving revision 1.10
+diff -u -p -r1.10 stdint.h
+--- newlib/libc/include/stdint.h       16 Aug 2006 21:39:43 -0000      1.10
++++ newlib/libc/include/stdint.h       12 Feb 2008 13:07:52 -0000
+@@ -38,7 +38,7 @@ extern "C" {
+ #if __STDINT_EXP(LONG_MAX) > 0x7fffffff
+ #define __have_long64 1
+ #elif __STDINT_EXP(LONG_MAX) == 0x7fffffff && !defined(__SPU__)
+-#define __have_long32 1
++/* #define __have_long32 1 */
+ #endif
+ 
+ #if __STDINT_EXP(SCHAR_MAX) == 0x7f
+
+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 88818d55e95a stubdom/stubdom-dm
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/stubdom/stubdom-dm        Tue Feb 12 14:02:15 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 88818d55e95a tools/ioemu/Makefile.target
--- a/tools/ioemu/Makefile.target       Tue Feb 12 11:37:45 2008 +0000
+++ b/tools/ioemu/Makefile.target       Tue Feb 12 14:02:15 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 88818d55e95a tools/ioemu/aes.c
--- a/tools/ioemu/aes.c Tue Feb 12 11:37:45 2008 +0000
+++ b/tools/ioemu/aes.c Tue Feb 12 14:02:15 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 88818d55e95a tools/ioemu/block-vbd.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/ioemu/block-vbd.c   Tue Feb 12 14:02:15 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 88818d55e95a tools/ioemu/block.c
--- a/tools/ioemu/block.c       Tue Feb 12 11:37:45 2008 +0000
+++ b/tools/ioemu/block.c       Tue Feb 12 14:02:15 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 88818d55e95a tools/ioemu/configure
--- a/tools/ioemu/configure     Tue Feb 12 11:37:45 2008 +0000
+++ b/tools/ioemu/configure     Tue Feb 12 14:02:15 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 88818d55e95a tools/ioemu/exec-all.h
--- a/tools/ioemu/exec-all.h    Tue Feb 12 11:37:45 2008 +0000
+++ b/tools/ioemu/exec-all.h    Tue Feb 12 14:02:15 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 88818d55e95a tools/ioemu/hw/ide.c
--- a/tools/ioemu/hw/ide.c      Tue Feb 12 11:37:45 2008 +0000
+++ b/tools/ioemu/hw/ide.c      Tue Feb 12 14:02:15 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(getpagesize(), MAX_MULT_SECTORS*512 + 4);
         if (i == 0)
             s->bs = hd0;
         else
diff -r 88818d55e95a tools/ioemu/hw/scsi-disk.c
--- a/tools/ioemu/hw/scsi-disk.c        Tue Feb 12 11:37:45 2008 +0000
+++ b/tools/ioemu/hw/scsi-disk.c        Tue Feb 12 14:02:15 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(getpagesize(), SCSI_DMA_BUF_SIZE);
     }
     r->dev = s;
     r->tag = tag;
diff -r 88818d55e95a tools/ioemu/hw/xen_machine_fv.c
--- a/tools/ioemu/hw/xen_machine_fv.c   Tue Feb 12 11:37:45 2008 +0000
+++ b/tools/ioemu/hw/xen_machine_fv.c   Tue Feb 12 14:02:15 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 88818d55e95a tools/ioemu/vl.c
--- a/tools/ioemu/vl.c  Tue Feb 12 11:37:45 2008 +0000
+++ b/tools/ioemu/vl.c  Tue Feb 12 14:02:15 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,6 +7967,7 @@ int main(int argc, char **argv)
     }
 #endif
 
+#ifndef CONFIG_STUBDOM
     /* Unblock SIGTERM and SIGHUP, which may have been blocked by the caller */
     signal(SIGHUP, SIG_DFL);
     sigemptyset(&set);
@@ -7935,6 +7975,7 @@ int main(int argc, char **argv)
     sigaddset(&set, SIGHUP);
     if (sigprocmask(SIG_UNBLOCK, &set, NULL) == -1)
         fprintf(stderr, "Failed to unblock SIGTERM and SIGHUP\n");
+#endif
 
     main_loop();
     quit_timers();
diff -r 88818d55e95a tools/ioemu/vl.h
--- a/tools/ioemu/vl.h  Tue Feb 12 11:37:45 2008 +0000
+++ b/tools/ioemu/vl.h  Tue Feb 12 14:02:15 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 88818d55e95a tools/ioemu/vnc.c
--- a/tools/ioemu/vnc.c Tue Feb 12 11:37:45 2008 +0000
+++ b/tools/ioemu/vnc.c Tue Feb 12 14:02:15 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 88818d55e95a tools/ioemu/xenstore.c
--- a/tools/ioemu/xenstore.c    Tue Feb 12 11:37:45 2008 +0000
+++ b/tools/ioemu/xenstore.c    Tue Feb 12 14:02:15 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 88818d55e95a tools/libxc/Makefile
--- a/tools/libxc/Makefile      Tue Feb 12 11:37:45 2008 +0000
+++ b/tools/libxc/Makefile      Tue Feb 12 14:02:15 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 88818d55e95a tools/libxc/ia64/Makefile
--- a/tools/libxc/ia64/Makefile Tue Feb 12 11:37:45 2008 +0000
+++ b/tools/libxc/ia64/Makefile Tue Feb 12 14:02:15 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 88818d55e95a tools/libxc/xc_minios.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/libxc/xc_minios.c   Tue Feb 12 14:02:15 2008 +0000
@@ -0,0 +1,313 @@
+/******************************************************************************
+ *
+ * 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 <types.h>
+#include <os.h>
+#include <mm.h>
+#include <lib.h>
+#include <events.h>
+#include <wait.h>
+#include <sys/mman.h>
+#include <errno.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>
+
+#include "xc_private.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 % getpagesize()));
+    return map_frames_ex(&mfn, size / getpagesize(), 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:
+ */

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