aboutsummaryrefslogtreecommitdiffstats
path: root/extras/mini-os
diff options
context:
space:
mode:
authorKeir Fraser <keir.fraser@citrix.com>2008-02-12 14:35:39 +0000
committerKeir Fraser <keir.fraser@citrix.com>2008-02-12 14:35:39 +0000
commit0243b256d6187ea610174531607366945e489605 (patch)
treefd2de9267b7493642626f8c84d7c81ebcd336bed /extras/mini-os
parent67bfbd67d1311a1a590b47e568a07622d4492873 (diff)
downloadxen-0243b256d6187ea610174531607366945e489605.tar.gz
xen-0243b256d6187ea610174531607366945e489605.tar.bz2
xen-0243b256d6187ea610174531607366945e489605.zip
Add stubdomain support. See stubdom/README for usage details.
- 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. - 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@eu.citrix.com>
Diffstat (limited to 'extras/mini-os')
-rw-r--r--extras/mini-os/Config.mk76
-rw-r--r--extras/mini-os/Makefile81
-rw-r--r--extras/mini-os/arch/ia64/Makefile4
-rw-r--r--extras/mini-os/arch/ia64/minios-ia64.lds12
-rw-r--r--extras/mini-os/arch/ia64/mm.c8
-rw-r--r--extras/mini-os/arch/x86/Makefile3
-rw-r--r--extras/mini-os/arch/x86/arch.mk8
-rw-r--r--extras/mini-os/arch/x86/minios-x86_32.lds12
-rw-r--r--extras/mini-os/arch/x86/minios-x86_64.lds12
-rw-r--r--extras/mini-os/arch/x86/mm.c17
-rw-r--r--extras/mini-os/arch/x86/x86_32.S6
-rw-r--r--extras/mini-os/arch/x86/x86_64.S6
-rw-r--r--extras/mini-os/blkfront.c46
-rw-r--r--extras/mini-os/include/arch/cc.h7
-rw-r--r--extras/mini-os/include/byteswap.h22
-rw-r--r--extras/mini-os/include/console.h3
-rw-r--r--extras/mini-os/include/errno.h7
-rw-r--r--extras/mini-os/include/fcntl.h3
-rw-r--r--extras/mini-os/include/fs.h1
-rw-r--r--extras/mini-os/include/ia64/arch_limits.h12
-rw-r--r--extras/mini-os/include/ia64/arch_mm.h4
-rw-r--r--extras/mini-os/include/ia64/page.h6
-rw-r--r--extras/mini-os/include/lib.h59
-rw-r--r--extras/mini-os/include/linux/types.h5
-rw-r--r--extras/mini-os/include/mm.h8
-rw-r--r--extras/mini-os/include/netfront.h4
-rw-r--r--extras/mini-os/include/posix/dirent.h24
-rw-r--r--extras/mini-os/include/posix/limits.h9
-rw-r--r--extras/mini-os/include/posix/netdb.h9
-rw-r--r--extras/mini-os/include/posix/netinet/in.h7
-rw-r--r--extras/mini-os/include/posix/netinet/tcp.h6
-rw-r--r--extras/mini-os/include/posix/pthread.h19
-rw-r--r--extras/mini-os/include/posix/stdlib.h8
-rw-r--r--extras/mini-os/include/posix/strings.h8
-rw-r--r--extras/mini-os/include/posix/sys/ioctl.h16
-rw-r--r--extras/mini-os/include/posix/sys/mman.h19
-rw-r--r--extras/mini-os/include/posix/sys/select.h7
-rw-r--r--extras/mini-os/include/posix/sys/socket.h31
-rw-r--r--extras/mini-os/include/posix/termios.h87
-rw-r--r--extras/mini-os/include/posix/time.h10
-rw-r--r--extras/mini-os/include/posix/unistd.h12
-rw-r--r--extras/mini-os/include/sched.h3
-rw-r--r--extras/mini-os/include/sys/time.h4
-rw-r--r--extras/mini-os/include/time.h11
-rw-r--r--extras/mini-os/include/x86/arch_limits.h20
-rw-r--r--extras/mini-os/include/x86/arch_mm.h22
-rw-r--r--extras/mini-os/include/x86/arch_sched.h4
-rw-r--r--extras/mini-os/include/x86/arch_spinlock.h1
-rw-r--r--extras/mini-os/include/x86/os.h1
-rw-r--r--extras/mini-os/lib/sys.c1083
-rw-r--r--extras/mini-os/lib/xs.c187
-rw-r--r--extras/mini-os/main-caml.c42
-rw-r--r--extras/mini-os/main.c167
-rw-r--r--extras/mini-os/minios.mk13
-rw-r--r--extras/mini-os/mm.c23
-rw-r--r--extras/mini-os/netfront.c98
-rw-r--r--extras/mini-os/sched.c44
57 files changed, 2324 insertions, 103 deletions
diff --git a/extras/mini-os/Config.mk b/extras/mini-os/Config.mk
new file mode 100644
index 0000000000..e38fae99cb
--- /dev/null
+++ b/extras/mini-os/Config.mk
@@ -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 --git a/extras/mini-os/Makefile b/extras/mini-os/Makefile
index a008143cf0..4811f0dbfd 100644
--- a/extras/mini-os/Makefile
+++ b/extras/mini-os/Makefile
@@ -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 lwip%.o $(LWO), $(OBJS))
-OBJS := $(filter-out $(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 --git a/extras/mini-os/arch/ia64/Makefile b/extras/mini-os/arch/ia64/Makefile
index fb5ca9fb72..6e46aa67ef 100644
--- a/extras/mini-os/arch/ia64/Makefile
+++ b/extras/mini-os/arch/ia64/Makefile
@@ -5,6 +5,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 --git a/extras/mini-os/arch/ia64/minios-ia64.lds b/extras/mini-os/arch/ia64/minios-ia64.lds
index 70435de11e..96911aa3fd 100644
--- a/extras/mini-os/arch/ia64/minios-ia64.lds
+++ b/extras/mini-os/arch/ia64/minios-ia64.lds
@@ -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 --git a/extras/mini-os/arch/ia64/mm.c b/extras/mini-os/arch/ia64/mm.c
index f557730257..f2291f918c 100644
--- a/extras/mini-os/arch/ia64/mm.c
+++ b/extras/mini-os/arch/ia64/mm.c
@@ -43,6 +43,14 @@ 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
print_phys_avail(void)
diff --git a/extras/mini-os/arch/x86/Makefile b/extras/mini-os/arch/x86/Makefile
index 22cfe82811..21f0958f6a 100644
--- a/extras/mini-os/arch/x86/Makefile
+++ b/extras/mini-os/arch/x86/Makefile
@@ -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 --git a/extras/mini-os/arch/x86/arch.mk b/extras/mini-os/arch/x86/arch.mk
index dd6bfe0b8d..1680362789 100644
--- a/extras/mini-os/arch/x86/arch.mk
+++ b/extras/mini-os/arch/x86/arch.mk
@@ -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 @@ ARCH_ASFLAGS += -DCONFIG_X86_PAE=1
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 --git a/extras/mini-os/arch/x86/minios-x86_32.lds b/extras/mini-os/arch/x86/minios-x86_32.lds
index 08ebe14328..df5301944f 100644
--- a/extras/mini-os/arch/x86/minios-x86_32.lds
+++ b/extras/mini-os/arch/x86/minios-x86_32.lds
@@ -16,6 +16,18 @@ SECTIONS
. = 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)
CONSTRUCTORS
diff --git a/extras/mini-os/arch/x86/minios-x86_64.lds b/extras/mini-os/arch/x86/minios-x86_64.lds
index 345c38640c..f93800236b 100644
--- a/extras/mini-os/arch/x86/minios-x86_64.lds
+++ b/extras/mini-os/arch/x86/minios-x86_64.lds
@@ -16,6 +16,18 @@ SECTIONS
. = 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)
CONSTRUCTORS
diff --git a/extras/mini-os/arch/x86/mm.c b/extras/mini-os/arch/x86/mm.c
index 082527d098..dd556e4741 100644
--- a/extras/mini-os/arch/x86/mm.c
+++ b/extras/mini-os/arch/x86/mm.c
@@ -448,6 +448,15 @@ static unsigned long demand_map_area_start;
#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(unsigned long cur_pfn)
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 --git a/extras/mini-os/arch/x86/x86_32.S b/extras/mini-os/arch/x86/x86_32.S
index 4b9a337c08..7f01851f0c 100644
--- a/extras/mini-os/arch/x86/x86_32.S
+++ b/extras/mini-os/arch/x86/x86_32.S
@@ -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:
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 --git a/extras/mini-os/arch/x86/x86_64.S b/extras/mini-os/arch/x86/x86_64.S
index fae2ae4cf5..c7a797db90 100644
--- a/extras/mini-os/arch/x86/x86_64.S
+++ b/extras/mini-os/arch/x86/x86_64.S
@@ -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:
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 --git a/extras/mini-os/blkfront.c b/extras/mini-os/blkfront.c
index 881efd3055..b83d5af345 100644
--- a/extras/mini-os/blkfront.c
+++ b/extras/mini-os/blkfront.c
@@ -15,6 +15,10 @@
#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 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(struct blkfront_dev *dev, uint8_t op)
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 *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 *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 --git a/extras/mini-os/include/arch/cc.h b/extras/mini-os/include/arch/cc.h
index 70191f0b30..e9a258d8bf 100644
--- a/extras/mini-os/include/arch/cc.h
+++ b/extras/mini-os/include/arch/cc.h
@@ -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 --git a/extras/mini-os/include/byteswap.h b/extras/mini-os/include/byteswap.h
new file mode 100644
index 0000000000..7c4ffe393c
--- /dev/null
+++ b/extras/mini-os/include/byteswap.h
@@ -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 --git a/extras/mini-os/include/console.h b/extras/mini-os/include/console.h
index 6ee04f1316..9ace8dfcb1 100644
--- a/extras/mini-os/include/console.h
+++ b/extras/mini-os/include/console.h
@@ -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_rx(char *buf, unsigned len, struct pt_regs *regs);
void xencons_tx(void);
void init_console(void);
+void console_print(char *data, int length);
#endif /* _LIB_CONSOLE_H_ */
diff --git a/extras/mini-os/include/errno.h b/extras/mini-os/include/errno.h
index 262ab3e0b4..2829420dd7 100644
--- a/extras/mini-os/include/errno.h
+++ b/extras/mini-os/include/errno.h
@@ -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 --git a/extras/mini-os/include/fcntl.h b/extras/mini-os/include/fcntl.h
index 64020795ab..34a6484d35 100644
--- a/extras/mini-os/include/fcntl.h
+++ b/extras/mini-os/include/fcntl.h
@@ -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 --git a/extras/mini-os/include/fs.h b/extras/mini-os/include/fs.h
index 1555a5adcc..4c822dfb20 100644
--- a/extras/mini-os/include/fs.h
+++ b/extras/mini-os/include/fs.h
@@ -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 --git a/extras/mini-os/include/ia64/arch_limits.h b/extras/mini-os/include/ia64/arch_limits.h
new file mode 100644
index 0000000000..c7bb9b6573
--- /dev/null
+++ b/extras/mini-os/include/ia64/arch_limits.h
@@ -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 --git a/extras/mini-os/include/ia64/arch_mm.h b/extras/mini-os/include/ia64/arch_mm.h
index 2a8e1c82a6..adc1da6d0f 100644
--- a/extras/mini-os/include/ia64/arch_mm.h
+++ b/extras/mini-os/include/ia64/arch_mm.h
@@ -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 --git a/extras/mini-os/include/ia64/page.h b/extras/mini-os/include/ia64/page.h
index 714227f172..67be0a555d 100644
--- a/extras/mini-os/include/ia64/page.h
+++ b/extras/mini-os/include/ia64/page.h
@@ -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 --git a/extras/mini-os/include/lib.h b/extras/mini-os/include/lib.h
index efe096bdba..2ddb8d07c8 100644
--- a/extras/mini-os/include/lib.h
+++ b/extras/mini-os/include/lib.h
@@ -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 --git a/extras/mini-os/include/linux/types.h b/extras/mini-os/include/linux/types.h
new file mode 100644
index 0000000000..f153ce8e42
--- /dev/null
+++ b/extras/mini-os/include/linux/types.h
@@ -0,0 +1,5 @@
+#ifndef _LINUX_TYPES_H_
+#define _LINUX_TYPES_H_
+#include <types.h>
+typedef u64 __u64;
+#endif /* _LINUX_TYPES_H_ */
diff --git a/extras/mini-os/include/mm.h b/extras/mini-os/include/mm.h
index 4319fa2640..8396ec6b31 100644
--- a/extras/mini-os/include/mm.h
+++ b/extras/mini-os/include/mm.h
@@ -36,8 +36,13 @@
#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);
unsigned long alloc_pages(int order);
@@ -61,5 +66,8 @@ void arch_init_p2m(unsigned long max_pfn_p);
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 --git a/extras/mini-os/include/netfront.h b/extras/mini-os/include/netfront.h
index 5c8ec9c4fa..acfc91944b 100644
--- a/extras/mini-os/include/netfront.h
+++ b/extras/mini-os/include/netfront.h
@@ -6,6 +6,10 @@ struct netfront_dev;
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 --git a/extras/mini-os/include/posix/dirent.h b/extras/mini-os/include/posix/dirent.h
new file mode 100644
index 0000000000..56b1d67258
--- /dev/null
+++ b/extras/mini-os/include/posix/dirent.h
@@ -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 --git a/extras/mini-os/include/posix/limits.h b/extras/mini-os/include/posix/limits.h
new file mode 100644
index 0000000000..ba800e33d2
--- /dev/null
+++ b/extras/mini-os/include/posix/limits.h
@@ -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 --git a/extras/mini-os/include/posix/netdb.h b/extras/mini-os/include/posix/netdb.h
new file mode 100644
index 0000000000..8f76a95b76
--- /dev/null
+++ b/extras/mini-os/include/posix/netdb.h
@@ -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 --git a/extras/mini-os/include/posix/netinet/in.h b/extras/mini-os/include/posix/netinet/in.h
new file mode 100644
index 0000000000..cc1a91076d
--- /dev/null
+++ b/extras/mini-os/include/posix/netinet/in.h
@@ -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 --git a/extras/mini-os/include/posix/netinet/tcp.h b/extras/mini-os/include/posix/netinet/tcp.h
new file mode 100644
index 0000000000..3e3b060467
--- /dev/null
+++ b/extras/mini-os/include/posix/netinet/tcp.h
@@ -0,0 +1,6 @@
+#ifndef _POSIX_SYS_TCP_H_
+#define _POSIX_SYS_TCP_H_
+
+#include <lwip/tcp.h>
+
+#endif /* _POSIX_SYS_TCP_H_ */
diff --git a/extras/mini-os/include/posix/pthread.h b/extras/mini-os/include/posix/pthread.h
new file mode 100644
index 0000000000..7e62001e3a
--- /dev/null
+++ b/extras/mini-os/include/posix/pthread.h
@@ -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 --git a/extras/mini-os/include/posix/stdlib.h b/extras/mini-os/include/posix/stdlib.h
new file mode 100644
index 0000000000..53e6289635
--- /dev/null
+++ b/extras/mini-os/include/posix/stdlib.h
@@ -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 --git a/extras/mini-os/include/posix/strings.h b/extras/mini-os/include/posix/strings.h
new file mode 100644
index 0000000000..8619ba2865
--- /dev/null
+++ b/extras/mini-os/include/posix/strings.h
@@ -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 --git a/extras/mini-os/include/posix/sys/ioctl.h b/extras/mini-os/include/posix/sys/ioctl.h
new file mode 100644
index 0000000000..ecf3080d5a
--- /dev/null
+++ b/extras/mini-os/include/posix/sys/ioctl.h
@@ -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 --git a/extras/mini-os/include/posix/sys/mman.h b/extras/mini-os/include/posix/sys/mman.h
new file mode 100644
index 0000000000..318d574877
--- /dev/null
+++ b/extras/mini-os/include/posix/sys/mman.h
@@ -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 --git a/extras/mini-os/include/posix/sys/select.h b/extras/mini-os/include/posix/sys/select.h
new file mode 100644
index 0000000000..5132c51224
--- /dev/null
+++ b/extras/mini-os/include/posix/sys/select.h
@@ -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 --git a/extras/mini-os/include/posix/sys/socket.h b/extras/mini-os/include/posix/sys/socket.h
new file mode 100644
index 0000000000..7c039a2f03
--- /dev/null
+++ b/extras/mini-os/include/posix/sys/socket.h
@@ -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 --git a/extras/mini-os/include/posix/termios.h b/extras/mini-os/include/posix/termios.h
new file mode 100644
index 0000000000..a57aee4556
--- /dev/null
+++ b/extras/mini-os/include/posix/termios.h
@@ -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 --git a/extras/mini-os/include/posix/time.h b/extras/mini-os/include/posix/time.h
new file mode 100644
index 0000000000..4f457cb5ad
--- /dev/null
+++ b/extras/mini-os/include/posix/time.h
@@ -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 --git a/extras/mini-os/include/posix/unistd.h b/extras/mini-os/include/posix/unistd.h
new file mode 100644
index 0000000000..0cd9396ec9
--- /dev/null
+++ b/extras/mini-os/include/posix/unistd.h
@@ -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 --git a/extras/mini-os/include/sched.h b/extras/mini-os/include/sched.h
index a3d2022b8a..ba0d4e3df9 100644
--- a/extras/mini-os/include/sched.h
+++ b/extras/mini-os/include/sched.h
@@ -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 --git a/extras/mini-os/include/sys/time.h b/extras/mini-os/include/sys/time.h
index 87887c27d1..d6623a4e77 100644
--- a/extras/mini-os/include/sys/time.h
+++ b/extras/mini-os/include/sys/time.h
@@ -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 --git a/extras/mini-os/include/time.h b/extras/mini-os/include/time.h
index 914f2fcff2..e28bf171d7 100644
--- a/extras/mini-os/include/time.h
+++ b/extras/mini-os/include/time.h
@@ -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 @@ s_time_t get_v_time(void);
u64 monotonic_clock(void);
void block_domain(s_time_t until);
-#endif /* _TIME_H_ */
+#endif /* _MINIOS_TIME_H_ */
diff --git a/extras/mini-os/include/x86/arch_limits.h b/extras/mini-os/include/x86/arch_limits.h
new file mode 100644
index 0000000000..7f0351c67f
--- /dev/null
+++ b/extras/mini-os/include/x86/arch_limits.h
@@ -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 --git a/extras/mini-os/include/x86/arch_mm.h b/extras/mini-os/include/x86/arch_mm.h
index c5e106e6da..7ad8bc14be 100644
--- a/extras/mini-os/include/x86/arch_mm.h
+++ b/extras/mini-os/include/x86/arch_mm.h
@@ -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)
@@ -177,9 +170,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. */
#ifdef CONFIG_X86_PAE
@@ -257,5 +247,11 @@ static __inline__ paddr_t machine_to_phys(maddr_t machine)
#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 --git a/extras/mini-os/include/x86/arch_sched.h b/extras/mini-os/include/x86/arch_sched.h
index 877440762e..d80323cd37 100644
--- a/extras/mini-os/include/x86/arch_sched.h
+++ b/extras/mini-os/include/x86/arch_sched.h
@@ -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(void)
#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 --git a/extras/mini-os/include/x86/arch_spinlock.h b/extras/mini-os/include/x86/arch_spinlock.h
index a181ed3c92..b711fe473c 100644
--- a/extras/mini-os/include/x86/arch_spinlock.h
+++ b/extras/mini-os/include/x86/arch_spinlock.h
@@ -4,6 +4,7 @@
#define __ARCH_ASM_SPINLOCK_H
#include <lib.h>
+#include "os.h"
#define ARCH_SPIN_LOCK_UNLOCKED (spinlock_t) { 1 }
diff --git a/extras/mini-os/include/x86/os.h b/extras/mini-os/include/x86/os.h
index 7a4433b3f9..7217d0b3ca 100644
--- a/extras/mini-os/include/x86/os.h
+++ b/extras/mini-os/include/x86/os.h
@@ -563,6 +563,7 @@ static __inline__ int synch_var_test_bit(int nr, volatile void * addr)
synch_var_test_bit((nr),(addr)))
+#undef ADDR
#endif /* not assembly */
#endif /* _OS_H_ */
diff --git a/extras/mini-os/lib/sys.c b/extras/mini-os/lib/sys.c
new file mode 100644
index 0000000000..f71e6966bd
--- /dev/null
+++ b/extras/mini-os/lib/sys.c
@@ -0,0 +1,1083 @@
+/*
+ * POSIX-compatible libc layer
+ *
+ * Samuel Thibault <Samuel.Thibault@eu.citrix.net>, 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 --git a/extras/mini-os/lib/xs.c b/extras/mini-os/lib/xs.c
new file mode 100644
index 0000000000..b654b0ee5d
--- /dev/null
+++ b/extras/mini-os/lib/xs.c
@@ -0,0 +1,187 @@
+/*
+ * libxs-compatible layer
+ *
+ * Samuel Thibault <Samuel.Thibault@eu.citrix.net>, 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 --git a/extras/mini-os/main-caml.c b/extras/mini-os/main-caml.c
new file mode 100644
index 0000000000..dd55aca38f
--- /dev/null
+++ b/extras/mini-os/main-caml.c
@@ -0,0 +1,42 @@
+/*
+ * Caml bootstrap
+ *
+ * Samuel Thibault <Samuel.Thibault@eu.citrix.net>, 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 --git a/extras/mini-os/main.c b/extras/mini-os/main.c
new file mode 100644
index 0000000000..345f7e9487
--- /dev/null
+++ b/extras/mini-os/main.c
@@ -0,0 +1,167 @@
+/*
+ * POSIX-compatible main layer
+ *
+ * Samuel Thibault <Samuel.Thibault@eu.citrix.net>, 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 --git a/extras/mini-os/minios.mk b/extras/mini-os/minios.mk
index fa6f6bd0c9..078c396fc2 100644
--- a/extras/mini-os/minios.mk
+++ b/extras/mini-os/minios.mk
@@ -9,7 +9,7 @@ debug = y
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,12 +24,10 @@ 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)
EXTRA_DEPS = $(MINI-OS_ROOT)/minios.mk \
@@ -44,18 +42,17 @@ extra_heads := $(foreach dir,$(EXTRA_INC),$(wildcard $(dir)/*.h))
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 --git a/extras/mini-os/mm.c b/extras/mini-os/mm.c
index 11e249d421..f204fa66ec 100644
--- a/extras/mini-os/mm.c
+++ b/extras/mini-os/mm.c
@@ -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 --git a/extras/mini-os/netfront.c b/extras/mini-os/netfront.c
index e3c56c10c4..095f55ca15 100644
--- a/extras/mini-os/netfront.c
+++ b/extras/mini-os/netfront.c
@@ -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)
@@ -50,6 +53,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_dev *dev)
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);
@@ -218,6 +243,22 @@ void netfront_handler(evtchn_port_t port, struct pt_regs *regs, void *data)
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])
{
xenbus_transaction_t xbt;
@@ -266,7 +307,12 @@ struct netfront_dev *init_netfront(char *nodename, void (*thenetif_rx)(unsigned
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 *dev, unsigned char* data,int len)
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 --git a/extras/mini-os/sched.c b/extras/mini-os/sched.c
index 18b3f01538..19a102f056 100644
--- a/extras/mini-os/sched.c
+++ b/extras/mini-os/sched.c
@@ -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, void (*function)(void *), void *data)
/* 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) {
@@ -185,6 +189,42 @@ struct thread* create_thread(char *name, void (*function)(void *), void *data)
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)
{
unsigned long flags;
@@ -228,6 +268,7 @@ void wake(struct thread *thread)
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);
}