[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Xen-devel] [PATCH 3/4] mini-os: Initial commit to port minios to ARM



Hi Thomas,

Thank you for the port of Minos on ARM!

This patch is a bit complex to read (nearly 3000 lines).

There is some change in the common code. It might be easier to move all those changes in a separate patch.

Same for the code imported from NetBSD.

Regards,


On 02/06/14 18:49, Thomas Leonard wrote:
From: Karim Raslan <karim.allah.ahmed@xxxxxxxxx>

On ARM, Mini-OS will boot and display some output on the Xen emergency
console (only visible if Xen is compiled in debug mode). Tested with:

make XEN_TARGET_ARCH=arm32 CROSS_COMPILE=arm-linux-gnueabihf- \
   CONFIG_TEST=n CONFIG_START_NETWORK=n CONFIG_BLKFRONT=n \
   CONFIG_NETFRONT=n CONFIG_FBFRONT=n CONFIG_KBDFRONT=n \
   CONFIG_CONSFRONT=n CONFIG_XC=n

Signed-off-by: Karim Allah Ahmed <karim.allah.ahmed@xxxxxxxxx>
[talex5@xxxxxxxxx: made x86_64 support work again]
[talex5@xxxxxxxxx: split into multiple patches]
Signed-off-by: Thomas Leonard <talex5@xxxxxxxxx>
---
  extras/mini-os/ARM-TODO.txt                        |  19 +
  extras/mini-os/Config.mk                           |   2 +
  extras/mini-os/Makefile                            |  12 +
  extras/mini-os/arch/arm/Makefile                   |  33 ++
  extras/mini-os/arch/arm/arch.mk                    |   6 +
  extras/mini-os/arch/arm/arm32.S                    | 211 +++++++++++
  extras/mini-os/arch/arm/divsi3.S                   | 404 +++++++++++++++++++++
  extras/mini-os/arch/arm/events.c                   |  24 ++
  extras/mini-os/arch/arm/hypercalls32.S             |  88 +++++
  extras/mini-os/arch/arm/ldivmod.S                  |  67 ++++
  extras/mini-os/arch/arm/ldivmod_helper.c           |  66 ++++
  extras/mini-os/arch/arm/minios-arm32.lds           |  73 ++++
  extras/mini-os/arch/arm/mm.c                       |  44 +++
  extras/mini-os/arch/arm/qdivrem.c                  | 270 ++++++++++++++
  extras/mini-os/arch/arm/sched.c                    |  32 ++
  extras/mini-os/arch/arm/setup.c                    |  55 +++
  extras/mini-os/arch/arm/time.c                     | 232 ++++++++++++
  extras/mini-os/arch/arm/xenbus.c                   |  36 ++
  extras/mini-os/arch/x86/events.c                   |  28 ++
  extras/mini-os/arch/x86/setup.c                    |  44 ++-
  extras/mini-os/arch/x86/time.c                     |   4 +-
  extras/mini-os/arch/x86/x86_32.S                   |   2 +-
  extras/mini-os/arch/x86/x86_64.S                   |   2 +-
  extras/mini-os/arch/x86/xenbus.c                   |  10 +
  extras/mini-os/console/console.c                   |   2 +
  extras/mini-os/drivers/gic.c                       | 179 +++++++++
  extras/mini-os/events.c                            |  32 +-
  extras/mini-os/gntmap.c                            |   1 +
  extras/mini-os/gnttab.c                            |   1 +
  extras/mini-os/hypervisor.c                        |  20 +-
  extras/mini-os/include/arm/arch_limits.h           |   9 +
  extras/mini-os/include/arm/arch_mm.h               |  37 ++
  extras/mini-os/include/arm/arch_sched.h            |  22 ++
  extras/mini-os/include/arm/arch_spinlock.h         |  49 +++
  extras/mini-os/include/arm/hypercall-arm32.h       | 173 +++++++++
  extras/mini-os/include/arm/os.h                    | 314 ++++++++++++++++
  extras/mini-os/include/arm/traps.h                 |  20 +
  extras/mini-os/include/console.h                   |   1 +
  extras/mini-os/include/hypervisor.h                |  19 +-
  extras/mini-os/include/mm.h                        |   2 +
  extras/mini-os/include/types.h                     |  73 +++-
  extras/mini-os/include/x86/arch_mm.h               |   2 +
  extras/mini-os/include/x86/os.h                    |  19 +-
  .../mini-os/include/x86/x86_64/hypercall-x86_64.h  |   1 +
  extras/mini-os/kernel.c                            |  78 ++--
  extras/mini-os/mm.c                                |   9 +-
  extras/mini-os/sched.c                             |   9 +-
  extras/mini-os/time.c                              |  12 +
  extras/mini-os/xenbus/xenbus.c                     |  18 +-
  49 files changed, 2758 insertions(+), 108 deletions(-)
  create mode 100644 extras/mini-os/ARM-TODO.txt
  create mode 100755 extras/mini-os/arch/arm/Makefile
  create mode 100644 extras/mini-os/arch/arm/arch.mk
  create mode 100644 extras/mini-os/arch/arm/arm32.S
  create mode 100644 extras/mini-os/arch/arm/divsi3.S
  create mode 100644 extras/mini-os/arch/arm/events.c
  create mode 100644 extras/mini-os/arch/arm/hypercalls32.S
  create mode 100644 extras/mini-os/arch/arm/ldivmod.S
  create mode 100644 extras/mini-os/arch/arm/ldivmod_helper.c
  create mode 100755 extras/mini-os/arch/arm/minios-arm32.lds
  create mode 100644 extras/mini-os/arch/arm/mm.c
  create mode 100644 extras/mini-os/arch/arm/qdivrem.c
  create mode 100644 extras/mini-os/arch/arm/sched.c
  create mode 100644 extras/mini-os/arch/arm/setup.c
  create mode 100644 extras/mini-os/arch/arm/time.c
  create mode 100644 extras/mini-os/arch/arm/xenbus.c
  create mode 100644 extras/mini-os/arch/x86/events.c
  create mode 100644 extras/mini-os/arch/x86/xenbus.c
  create mode 100644 extras/mini-os/drivers/gic.c
  create mode 100644 extras/mini-os/include/arm/arch_limits.h
  create mode 100644 extras/mini-os/include/arm/arch_mm.h
  create mode 100644 extras/mini-os/include/arm/arch_sched.h
  create mode 100755 extras/mini-os/include/arm/arch_spinlock.h
  create mode 100644 extras/mini-os/include/arm/hypercall-arm32.h
  create mode 100644 extras/mini-os/include/arm/os.h
  create mode 100644 extras/mini-os/include/arm/traps.h
  create mode 100644 extras/mini-os/time.c

diff --git a/extras/mini-os/ARM-TODO.txt b/extras/mini-os/ARM-TODO.txt
new file mode 100644
index 0000000..57d531a
--- /dev/null
+++ b/extras/mini-os/ARM-TODO.txt
@@ -0,0 +1,19 @@
+* os.h bit manipulation, write optimized assembly code
+* support abort exception handling ( and others )
+* scheduling!
+* use proper memory types and enable caches (L1 and L2)
+* Use LDREX and STREX in xchg implementation ( code already there but it 
causes an abort, I think because of using strong-ordered memory with disabled 
L1 caches - something to do with the implementation of the monitor on cortex-a7 
)
+* gic request_irq implementation, currently all IRQs all hardcoded in gic irq 
handler.
+* use device tree instead of the currently hardcoded values
+* Add virtual memory support and make vstart = 0 ( use 4k descriptors instead 
of 1M descriptors )
+* sched
+* fini_gnttab
+* fini_time
+* bind_*
+* add multiple cpu support (?)
+* map_frames
+* clean up the code and remove redundent code between arm and x86
+* remove start_info structure from the common code
+* make sure that wallclock is functioning properly
+* console support
+* evtchn_get_peercontext
diff --git a/extras/mini-os/Config.mk b/extras/mini-os/Config.mk
index d61877b..4ecde54 100644
--- a/extras/mini-os/Config.mk
+++ b/extras/mini-os/Config.mk
@@ -12,6 +12,8 @@ export XEN_INTERFACE_VERSION
  # If not x86 then use $(XEN_TARGET_ARCH)
  ifeq ($(findstring x86_,$(XEN_TARGET_ARCH)),x86_)
  TARGET_ARCH_FAM = x86
+else ifeq ($(findstring arm,$(XEN_TARGET_ARCH)),arm)
+TARGET_ARCH_FAM = arm
  else
  TARGET_ARCH_FAM = $(XEN_TARGET_ARCH)
  endif
diff --git a/extras/mini-os/Makefile b/extras/mini-os/Makefile
index 50d038b..0fd38a8 100644
--- a/extras/mini-os/Makefile
+++ b/extras/mini-os/Makefile
@@ -72,6 +72,11 @@ TARGET := mini-os
  # Subdirectories common to mini-os
  SUBDIRS := lib xenbus console

+ifeq ($(XEN_TARGET_ARCH),arm32)
+# ARM drivers
+src-y += drivers/gic.c
+endif
+
  src-$(CONFIG_BLKFRONT) += blkfront.c
  src-$(CONFIG_TPMFRONT) += tpmfront.c
  src-$(CONFIG_TPM_TIS) += tpm_tis.c
@@ -82,6 +87,7 @@ src-$(CONFIG_FBFRONT) += fbfront.c
  src-y += gntmap.c
  src-y += gnttab.c
  src-y += hypervisor.c
+src-y += time.c
  src-y += kernel.c
  src-y += lock.c
  src-y += main.c
@@ -92,7 +98,9 @@ src-y += sched.c
  src-$(CONFIG_TEST) += test.c

  src-y += lib/ctype.c
+ifneq ($(XEN_TARGET_ARCH),arm32)
  src-y += lib/math.c
+endif
  src-y += lib/printf.c
  src-y += lib/stack_chk_fail.c
  src-y += lib/string.c
@@ -178,7 +186,11 @@ $(OBJ_DIR)/$(TARGET): links include/list.h $(OBJS) 
$(APP_O) arch_lib
        $(LD) -r $(LDFLAGS) $(HEAD_OBJ) $(APP_O) $(OBJS) $(LDARCHLIB) $(LDLIBS) 
-o $@.o
        $(OBJCOPY) -w -G $(GLOBAL_PREFIX)* -G _start $@.o $@.o
        $(LD) $(LDFLAGS) $(LDFLAGS_FINAL) $@.o $(EXTRA_OBJS) -o $@
+ifeq ($(XEN_TARGET_ARCH),arm32)
+       $(OBJCOPY) -O binary $@ $@.img
+else
        gzip -f -9 -c $@ >$@.gz
+endif

  .PHONY: clean arch_clean

diff --git a/extras/mini-os/arch/arm/Makefile b/extras/mini-os/arch/arm/Makefile
new file mode 100755
index 0000000..d8ecc88
--- /dev/null
+++ b/extras/mini-os/arch/arm/Makefile
@@ -0,0 +1,33 @@
+#
+# x86 architecture specific makefiles.
+# It's is used for x86_32, x86_32y and x86_64
+#
+
+XEN_ROOT = $(CURDIR)/../../../..
+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 $(XEN_TARGET_ARCH).S
+# This is handled in $(HEAD_ARCH_OBJ)
+ARCH_SRCS := $(wildcard *.c)
+
+# The objects built from the sources.
+ARCH_OBJS := $(patsubst %.c,$(OBJ_DIR)/%.o,$(ARCH_SRCS))
+
+ARCH_OBJS += hypercalls32.o divsi3.o ldivmod.o
+
+all: $(OBJ_DIR)/$(ARCH_LIB)
+
+# $(HEAD_ARCH_OBJ) is only build here, needed on linking
+# in ../../Makefile.
+$(OBJ_DIR)/$(ARCH_LIB): $(ARCH_OBJS) $(OBJ_DIR)/$(HEAD_ARCH_OBJ)
+       $(AR) rv $(OBJ_DIR)/$(ARCH_LIB) $(ARCH_OBJS)
+
+clean:
+       rm -f $(OBJ_DIR)/$(ARCH_LIB) $(ARCH_OBJS) $(OBJ_DIR)/$(HEAD_ARCH_OBJ)
+
diff --git a/extras/mini-os/arch/arm/arch.mk b/extras/mini-os/arch/arm/arch.mk
new file mode 100644
index 0000000..d2e0946
--- /dev/null
+++ b/extras/mini-os/arch/arm/arch.mk
@@ -0,0 +1,6 @@
+ifeq ($(XEN_TARGET_ARCH),arm32)
+ARCH_CFLAGS  := -march=armv7-a -marm -fms-extensions -D__arm__ 
#-DCPU_EXCLUSIVE_LDST
+EXTRA_INC += $(TARGET_ARCH_FAM)/$(XEN_TARGET_ARCH)
+EXTRA_SRC += arch/$(EXTRA_INC)
+endif
+
diff --git a/extras/mini-os/arch/arm/arm32.S b/extras/mini-os/arch/arm/arm32.S
new file mode 100644
index 0000000..2dd0f6c
--- /dev/null
+++ b/extras/mini-os/arch/arm/arm32.S
@@ -0,0 +1,211 @@
+#define PHYS_START (0x80008000)
+
+.section .text
+
+.globl _start
+_start:
+       @ zImage header
+.rept   8
+        mov     r0, r0
+.endr
+        b       1f
+        .word   0x016f2818      @ Magic numbers to help the loader
+        .word   _start         @ absolute load/run zImage address
+        .word   _end - _start   @ zImage size
+       @ end of zImage header
+
+1:
+#if FIXME
+@ core processor specific initialization
+       @ Initialize ACTLR core register
+       mrc p15, 0, <Rt>, c1, c0, 1
+       mcr p15, 0, <Rt>, c1, c0, 1
+#endif
+
+@ Save dtb pointer passed by the hypervisor
+       mov     r4, r2          @ save dtb pointer
+
+@ Build pagetables
+       bl      build_pagetables
+
+       ldr     r2, =page_dir
+       MCR     p15, 0, r2, c2, c0, 0   @ set ttbr0
+
+       @ Set access permission for domains
+       mov     r0, #0x3
+       MCR     p15, 0, r0, c3, c0, 0
+       isb
+       
+       ldr     r0, =mmu_switched
+
+       @ enable mmu / sctlr
+       mrc     p15, 0, r1, c1, c0, 0   @ read sctlr
+       orr     r1, r1, #0x1            @ enable mmu
+       @orr    r1, r1, #0x4            @ enable cache
+       orr     r1, r1, #0x02           @ enable barrier enable
+       @mcr    p15, 0, r1, c1, c0, 0   @ write sctlr
+       isb
+
+       @ jump to the virtual address now
+       mov     pc, r0
+
+@ If we're here, then we're very lucky
+mmu_switched:
+
+@ set VBAR = exception_vector_table
+       @ SCTLR.V = 0
+       adr     r0, exception_vector_table
+       mcr     p15, 0, r0, c12, c0, 0
+
+@ load stack
+       ldr     sp, =stack
+       add     sp, sp, #(4*4*1024)
+
+
+       mov     r0, r4          @ set r0 = dtb pointer
+       b       arch_init
+
+
+@ Populate the whole pagedir with 1MB section descriptors for now (1-1 mapping)
+build_pagetables:
+       ldr     r0, =(0x2 + (1 << 16) + (1<<19)) @ First section entry 
(sharable + NS ).
+       ldr     r1, =page_dir
+       add     r2, r1, #(4*4*1024) @ Limit
+
+1:
+       str     r0, [r1] @ write the section entry
+
+       add     r0, r0, #(1 << 20) @ next physical page.
+       add     r1, r1, #4 @ next pagedir entry
+       cmp     r1, r2
+       bne     1b
+
+       mov     pc, lr
+
+.pushsection .data
+.align 13
+.globl stack
+stack:
+       .fill (4*1024), 4, 0x0
+.align 13
+irqstack:
+       .fill (1024), 4, 0x0
+.globl shared_info_page
+.align 13
+shared_info_page:
+       .fill (1024), 4, 0x0
+.align 14
+page_dir:
+       .fill (4*1024), 4, 0x0
+
+.popsection
+
+@ exception base address
+.align 5
+.globl exception_vector_table
+exception_vector_table:
+       b       . @ reset
+       b       . @ undefined instruction
+       b       . @ supervisor call
+       b       . @ prefetch call
+       b       . @ prefetch abort
+       b       . @ data abort //FIXME CLREX
+       b       irq_handler @ irq
+       b       firq_handler @ firq
+
+irq_handler:
+firq_handler:
+       ldr     sp, =irqstack
+       add     sp, sp, #(4*1024)
+
+       @ Save registers
+       stmda   sp!, {r0 - r12}
+       stmda   sp!, {lr}
+
+       @ FIXME Find interrupt id and dispatch to the correct handler.
+       @ If event_irq
+       ldr     r0, IRQ_handler
+       cmp     r0, #0
+       beq     . @ If no IRQ handler was setup, just get stuck here!
+
+       adr     lr, 1f
+       mov     pc, r0
+1:
+       @bl     do_hypervisor_callback
+
+       @ Restore registers
+       ldmib   sp!, {lr}
+       ldmib   sp!, {r0 - r12}
+
+       @ Return from IRQ
+       subs    pc, lr, #4
+
+.globl IRQ_handler
+IRQ_handler:
+       .long   0x0
+
+
+.globl __arch_switch_threads
+@ r0 = &prev->sp & r1 = &(next->sp)
+__arch_switch_threads:
+       @ store sp, ip for prev thread
+       str     sp, [r0] @ sp
+       str     lr, [r0, #4] @ ip
+       str     fp, [sp, #-4] @ store fp on the stack
+       @ Load sp, ip for next thread
+       ldr     sp, [r1] @ sp
+       ldr     lr, [r1, #4] @ ip
+       ldr     fp, [sp, #-4] @ restore fp from the stack
+       mov     pc, lr
+
+#if 0
+pagetables_code:
+       bl      build_pagetables
+
+       ldr     r2, =(page_dir+PHYS_START)
+       MCR     p15, 0, r2, c2, c0, 0   @ set ttbr0
+
+       @ Set access permission for domains
+       mov     r0, #0x3
+       MCR     p15, 0, r0, c3, c0, 0
+
+       ldr     r0, =mmu_switched
+
+       @ enable mmu / sctlr
+       isb
+       MRC     p15, 0, r1, c1, c0, 0   @ read sctlr
+       orr     r1, r1, #0x1
+       MCR     p15, 0, r1, c1, c0, 0   @ write sctlr
+       MRC     p15, 0, r1, c0, c0, 0   @ read id reg
+
+       @ jump to the virtual address now
+       mov     pc, r0
+
+mmu_switched:
+       b       .
+
+build_pagetables:
+       ldr     r2, =(page_dir + PHYS_START)
+       ldr     r0, =(pagetable + PHYS_START + 1)
+       str     r0, [r2]
+
+       ldr     r2, =(pagetable + PHYS_START)
+       add     r1, r2, #1000
+
+       @ setup entry
+       ldr     r0, =(PHYS_START + 0x3)
+2:
+       str     r0, [r2], #4
+       add     r0, r0, #1 << 12
+       cmp     r2, r1
+       bne     2b
+       mov     pc, lr
+
+.pushsection .data
+.align 14
+page_dir:
+       .fill (1024), 4, 0x0
+pagetable:
+       .fill (1024*50), 4, 0x0
+.popsection
+#endif
diff --git a/extras/mini-os/arch/arm/divsi3.S b/extras/mini-os/arch/arm/divsi3.S
new file mode 100644
index 0000000..fa92233
--- /dev/null
+++ b/extras/mini-os/arch/arm/divsi3.S
@@ -0,0 +1,404 @@
+/*     $NetBSD: divsi3.S,v 1.4 2003/04/05 23:27:15 bjh21 Exp $ */
+
+/*-
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#define ENTRY_NP(symbol) \
+       .globl symbol;  \
+       symbol:
+
+#define END(symbol)
+
+/*
+ * stack is aligned as there's a possibility of branching to L_overflow
+ * which makes a C call
+ */
+
+ENTRY_NP(__umodsi3)
+       stmfd   sp!, {lr}
+       sub     sp, sp, #4      /* align stack */
+       bl      .L_udivide
+       add     sp, sp, #4      /* unalign stack */
+       mov     r0, r1
+       ldmfd   sp!, {pc}
+END(__umodsi3)
+
+ENTRY_NP(__modsi3)
+       stmfd   sp!, {lr}
+       sub     sp, sp, #4      /* align stack */
+       bl      .L_divide
+       add     sp, sp, #4      /* unalign stack */
+       mov     r0, r1
+       ldmfd   sp!, {pc}
+
+.L_overflow:
+       /* XXX should cause a fatal error */
+       mvn     r0, #0
+       mov     pc, lr
+
+END(__modsi3)
+
+#ifdef __ARM_EABI__
+ENTRY_NP(__aeabi_uidiv)
+ENTRY_NP(__aeabi_uidivmod)
+#endif
+ENTRY_NP(__udivsi3)
+.L_udivide:                            /* r0 = r0 / r1; r1 = r0 % r1 */
+       eor     r0, r1, r0
+       eor     r1, r0, r1
+       eor     r0, r1, r0
+                                       /* r0 = r1 / r0; r1 = r1 % r0 */
+       cmp     r0, #1
+       bcc     .L_overflow
+       beq     .L_divide_l0
+       mov     ip, #0
+       movs    r1, r1
+       bpl     .L_divide_l1
+       orr     ip, ip, #0x20000000     /* ip bit 0x20000000 = -ve r1 */
+       movs    r1, r1, lsr #1
+       orrcs   ip, ip, #0x10000000     /* ip bit 0x10000000 = bit 0 of r1 */
+       b       .L_divide_l1
+
+.L_divide_l0:                          /* r0 == 1 */
+       mov     r0, r1
+       mov     r1, #0
+       mov     pc, lr
+#ifdef __ARM_EABI__
+END(__aeabi_uidiv)
+END(__aeabi_uidivmod)
+#endif
+END(__udivsi3)
+
+#ifdef __ARM_EABI__
+ENTRY_NP(__aeabi_idiv)
+ENTRY_NP(__aeabi_idivmod)
+#endif
+ENTRY_NP(__divsi3)
+.L_divide:                             /* r0 = r0 / r1; r1 = r0 % r1 */
+       eor     r0, r1, r0
+       eor     r1, r0, r1
+       eor     r0, r1, r0
+                                       /* r0 = r1 / r0; r1 = r1 % r0 */
+       cmp     r0, #1
+       bcc     .L_overflow
+       beq     .L_divide_l0
+       ands    ip, r0, #0x80000000
+       rsbmi   r0, r0, #0
+       ands    r2, r1, #0x80000000
+       eor     ip, ip, r2
+       rsbmi   r1, r1, #0
+       orr     ip, r2, ip, lsr #1      /* ip bit 0x40000000 = -ve division */
+                                       /* ip bit 0x80000000 = -ve remainder */
+
+.L_divide_l1:
+       mov     r2, #1
+       mov     r3, #0
+
+       /*
+        * If the highest bit of the dividend is set, we have to be
+        * careful when shifting the divisor. Test this.
+        */
+       movs    r1,r1
+       bpl     .L_old_code
+
+       /*
+        * At this point, the highest bit of r1 is known to be set.
+        * We abuse this below in the tst instructions.
+        */
+       tst     r1, r0 /*, lsl #0 */
+       bmi     .L_divide_b1
+       tst     r1, r0, lsl #1
+       bmi     .L_divide_b2
+       tst     r1, r0, lsl #2
+       bmi     .L_divide_b3
+       tst     r1, r0, lsl #3
+       bmi     .L_divide_b4
+       tst     r1, r0, lsl #4
+       bmi     .L_divide_b5
+       tst     r1, r0, lsl #5
+       bmi     .L_divide_b6
+       tst     r1, r0, lsl #6
+       bmi     .L_divide_b7
+       tst     r1, r0, lsl #7
+       bmi     .L_divide_b8
+       tst     r1, r0, lsl #8
+       bmi     .L_divide_b9
+       tst     r1, r0, lsl #9
+       bmi     .L_divide_b10
+       tst     r1, r0, lsl #10
+       bmi     .L_divide_b11
+       tst     r1, r0, lsl #11
+       bmi     .L_divide_b12
+       tst     r1, r0, lsl #12
+       bmi     .L_divide_b13
+       tst     r1, r0, lsl #13
+       bmi     .L_divide_b14
+       tst     r1, r0, lsl #14
+       bmi     .L_divide_b15
+       tst     r1, r0, lsl #15
+       bmi     .L_divide_b16
+       tst     r1, r0, lsl #16
+       bmi     .L_divide_b17
+       tst     r1, r0, lsl #17
+       bmi     .L_divide_b18
+       tst     r1, r0, lsl #18
+       bmi     .L_divide_b19
+       tst     r1, r0, lsl #19
+       bmi     .L_divide_b20
+       tst     r1, r0, lsl #20
+       bmi     .L_divide_b21
+       tst     r1, r0, lsl #21
+       bmi     .L_divide_b22
+       tst     r1, r0, lsl #22
+       bmi     .L_divide_b23
+       tst     r1, r0, lsl #23
+       bmi     .L_divide_b24
+       tst     r1, r0, lsl #24
+       bmi     .L_divide_b25
+       tst     r1, r0, lsl #25
+       bmi     .L_divide_b26
+       tst     r1, r0, lsl #26
+       bmi     .L_divide_b27
+       tst     r1, r0, lsl #27
+       bmi     .L_divide_b28
+       tst     r1, r0, lsl #28
+       bmi     .L_divide_b29
+       tst     r1, r0, lsl #29
+       bmi     .L_divide_b30
+       tst     r1, r0, lsl #30
+       bmi     .L_divide_b31
+/*
+ * instead of:
+ *     tst     r1, r0, lsl #31
+ *     bmi     .L_divide_b32
+ */
+       b       .L_divide_b32
+
+.L_old_code:
+       cmp     r1, r0
+       bcc     .L_divide_b0
+       cmp     r1, r0, lsl #1
+       bcc     .L_divide_b1
+       cmp     r1, r0, lsl #2
+       bcc     .L_divide_b2
+       cmp     r1, r0, lsl #3
+       bcc     .L_divide_b3
+       cmp     r1, r0, lsl #4
+       bcc     .L_divide_b4
+       cmp     r1, r0, lsl #5
+       bcc     .L_divide_b5
+       cmp     r1, r0, lsl #6
+       bcc     .L_divide_b6
+       cmp     r1, r0, lsl #7
+       bcc     .L_divide_b7
+       cmp     r1, r0, lsl #8
+       bcc     .L_divide_b8
+       cmp     r1, r0, lsl #9
+       bcc     .L_divide_b9
+       cmp     r1, r0, lsl #10
+       bcc     .L_divide_b10
+       cmp     r1, r0, lsl #11
+       bcc     .L_divide_b11
+       cmp     r1, r0, lsl #12
+       bcc     .L_divide_b12
+       cmp     r1, r0, lsl #13
+       bcc     .L_divide_b13
+       cmp     r1, r0, lsl #14
+       bcc     .L_divide_b14
+       cmp     r1, r0, lsl #15
+       bcc     .L_divide_b15
+       cmp     r1, r0, lsl #16
+       bcc     .L_divide_b16
+       cmp     r1, r0, lsl #17
+       bcc     .L_divide_b17
+       cmp     r1, r0, lsl #18
+       bcc     .L_divide_b18
+       cmp     r1, r0, lsl #19
+       bcc     .L_divide_b19
+       cmp     r1, r0, lsl #20
+       bcc     .L_divide_b20
+       cmp     r1, r0, lsl #21
+       bcc     .L_divide_b21
+       cmp     r1, r0, lsl #22
+       bcc     .L_divide_b22
+       cmp     r1, r0, lsl #23
+       bcc     .L_divide_b23
+       cmp     r1, r0, lsl #24
+       bcc     .L_divide_b24
+       cmp     r1, r0, lsl #25
+       bcc     .L_divide_b25
+       cmp     r1, r0, lsl #26
+       bcc     .L_divide_b26
+       cmp     r1, r0, lsl #27
+       bcc     .L_divide_b27
+       cmp     r1, r0, lsl #28
+       bcc     .L_divide_b28
+       cmp     r1, r0, lsl #29
+       bcc     .L_divide_b29
+       cmp     r1, r0, lsl #30
+       bcc     .L_divide_b30
+.L_divide_b32:
+       cmp     r1, r0, lsl #31
+       subhs   r1, r1,r0, lsl #31
+       addhs   r3, r3,r2, lsl #31
+.L_divide_b31:
+       cmp     r1, r0, lsl #30
+       subhs   r1, r1,r0, lsl #30
+       addhs   r3, r3,r2, lsl #30
+.L_divide_b30:
+       cmp     r1, r0, lsl #29
+       subhs   r1, r1,r0, lsl #29
+       addhs   r3, r3,r2, lsl #29
+.L_divide_b29:
+       cmp     r1, r0, lsl #28
+       subhs   r1, r1,r0, lsl #28
+       addhs   r3, r3,r2, lsl #28
+.L_divide_b28:
+       cmp     r1, r0, lsl #27
+       subhs   r1, r1,r0, lsl #27
+       addhs   r3, r3,r2, lsl #27
+.L_divide_b27:
+       cmp     r1, r0, lsl #26
+       subhs   r1, r1,r0, lsl #26
+       addhs   r3, r3,r2, lsl #26
+.L_divide_b26:
+       cmp     r1, r0, lsl #25
+       subhs   r1, r1,r0, lsl #25
+       addhs   r3, r3,r2, lsl #25
+.L_divide_b25:
+       cmp     r1, r0, lsl #24
+       subhs   r1, r1,r0, lsl #24
+       addhs   r3, r3,r2, lsl #24
+.L_divide_b24:
+       cmp     r1, r0, lsl #23
+       subhs   r1, r1,r0, lsl #23
+       addhs   r3, r3,r2, lsl #23
+.L_divide_b23:
+       cmp     r1, r0, lsl #22
+       subhs   r1, r1,r0, lsl #22
+       addhs   r3, r3,r2, lsl #22
+.L_divide_b22:
+       cmp     r1, r0, lsl #21
+       subhs   r1, r1,r0, lsl #21
+       addhs   r3, r3,r2, lsl #21
+.L_divide_b21:
+       cmp     r1, r0, lsl #20
+       subhs   r1, r1,r0, lsl #20
+       addhs   r3, r3,r2, lsl #20
+.L_divide_b20:
+       cmp     r1, r0, lsl #19
+       subhs   r1, r1,r0, lsl #19
+       addhs   r3, r3,r2, lsl #19
+.L_divide_b19:
+       cmp     r1, r0, lsl #18
+       subhs   r1, r1,r0, lsl #18
+       addhs   r3, r3,r2, lsl #18
+.L_divide_b18:
+       cmp     r1, r0, lsl #17
+       subhs   r1, r1,r0, lsl #17
+       addhs   r3, r3,r2, lsl #17
+.L_divide_b17:
+       cmp     r1, r0, lsl #16
+       subhs   r1, r1,r0, lsl #16
+       addhs   r3, r3,r2, lsl #16
+.L_divide_b16:
+       cmp     r1, r0, lsl #15
+       subhs   r1, r1,r0, lsl #15
+       addhs   r3, r3,r2, lsl #15
+.L_divide_b15:
+       cmp     r1, r0, lsl #14
+       subhs   r1, r1,r0, lsl #14
+       addhs   r3, r3,r2, lsl #14
+.L_divide_b14:
+       cmp     r1, r0, lsl #13
+       subhs   r1, r1,r0, lsl #13
+       addhs   r3, r3,r2, lsl #13
+.L_divide_b13:
+       cmp     r1, r0, lsl #12
+       subhs   r1, r1,r0, lsl #12
+       addhs   r3, r3,r2, lsl #12
+.L_divide_b12:
+       cmp     r1, r0, lsl #11
+       subhs   r1, r1,r0, lsl #11
+       addhs   r3, r3,r2, lsl #11
+.L_divide_b11:
+       cmp     r1, r0, lsl #10
+       subhs   r1, r1,r0, lsl #10
+       addhs   r3, r3,r2, lsl #10
+.L_divide_b10:
+       cmp     r1, r0, lsl #9
+       subhs   r1, r1,r0, lsl #9
+       addhs   r3, r3,r2, lsl #9
+.L_divide_b9:
+       cmp     r1, r0, lsl #8
+       subhs   r1, r1,r0, lsl #8
+       addhs   r3, r3,r2, lsl #8
+.L_divide_b8:
+       cmp     r1, r0, lsl #7
+       subhs   r1, r1,r0, lsl #7
+       addhs   r3, r3,r2, lsl #7
+.L_divide_b7:
+       cmp     r1, r0, lsl #6
+       subhs   r1, r1,r0, lsl #6
+       addhs   r3, r3,r2, lsl #6
+.L_divide_b6:
+       cmp     r1, r0, lsl #5
+       subhs   r1, r1,r0, lsl #5
+       addhs   r3, r3,r2, lsl #5
+.L_divide_b5:
+       cmp     r1, r0, lsl #4
+       subhs   r1, r1,r0, lsl #4
+       addhs   r3, r3,r2, lsl #4
+.L_divide_b4:
+       cmp     r1, r0, lsl #3
+       subhs   r1, r1,r0, lsl #3
+       addhs   r3, r3,r2, lsl #3
+.L_divide_b3:
+       cmp     r1, r0, lsl #2
+       subhs   r1, r1,r0, lsl #2
+       addhs   r3, r3,r2, lsl #2
+.L_divide_b2:
+       cmp     r1, r0, lsl #1
+       subhs   r1, r1,r0, lsl #1
+       addhs   r3, r3,r2, lsl #1
+.L_divide_b1:
+       cmp     r1, r0
+       subhs   r1, r1, r0
+       addhs   r3, r3, r2
+.L_divide_b0:
+
+       tst     ip, #0x20000000
+       bne     .L_udivide_l1
+       mov     r0, r3
+       cmp     ip, #0
+       rsbmi   r1, r1, #0
+       movs    ip, ip, lsl #1
+       bicmi   r0, r0, #0x80000000     /* Fix incase we divided 0x80000000 */
+       rsbmi   r0, r0, #0
+       mov     pc, lr
+
+.L_udivide_l1:
+       tst     ip, #0x10000000
+       mov     r1, r1, lsl #1
+       orrne   r1, r1, #1
+       mov     r3, r3, lsl #1
+       cmp     r1, r0
+       subhs   r1, r1, r0
+       addhs   r3, r3, r2
+       mov     r0, r3
+       mov     pc, lr
+END(__aeabi_idiv)
+END(__aeabi_idivmod)
+END(__divsi3)
+
diff --git a/extras/mini-os/arch/arm/events.c b/extras/mini-os/arch/arm/events.c
new file mode 100644
index 0000000..6e579e7
--- /dev/null
+++ b/extras/mini-os/arch/arm/events.c
@@ -0,0 +1,24 @@
+#include <mini-os/os.h>
+#include <mini-os/events.h>
+#include <mini-os/hypervisor.h>
+
+static void virq_debug(evtchn_port_t port, struct pt_regs *regs, void *params)
+{
+       printk("Received a virq_debug event\n");
+}
+
+evtchn_port_t debug_port = -1;
+void arch_init_events(void) {
+       debug_port = bind_virq(VIRQ_DEBUG, (evtchn_handler_t)virq_debug, 0);
+       if(debug_port == -1)
+               BUG();
+       unmask_evtchn(debug_port);
+}
+
+void arch_fini_events(void) {
+       if(debug_port != -1)
+       {
+               mask_evtchn(debug_port);
+               unbind_evtchn(debug_port);
+       }
+}
diff --git a/extras/mini-os/arch/arm/hypercalls32.S 
b/extras/mini-os/arch/arm/hypercalls32.S
new file mode 100644
index 0000000..e2f21c4
--- /dev/null
+++ b/extras/mini-os/arch/arm/hypercalls32.S
@@ -0,0 +1,88 @@
+#define __HYPERVISOR_set_trap_table        0
+#define __HYPERVISOR_mmu_update            1
+#define __HYPERVISOR_set_gdt               2
+#define __HYPERVISOR_stack_switch          3
+#define __HYPERVISOR_set_callbacks         4
+#define __HYPERVISOR_fpu_taskswitch        5
+#define __HYPERVISOR_sched_op_compat       6 /* compat since 0x00030101 */
+#define __HYPERVISOR_platform_op           7
+#define __HYPERVISOR_set_debugreg          8
+#define __HYPERVISOR_get_debugreg          9
+#define __HYPERVISOR_update_descriptor    10
+#define __HYPERVISOR_memory_op            12
+#define __HYPERVISOR_multicall            13
+#define __HYPERVISOR_update_va_mapping    14
+#define __HYPERVISOR_set_timer_op         15
+#define __HYPERVISOR_event_channel_op_compat 16 /* compat since 0x00030202 */
+#define __HYPERVISOR_xen_version          17
+#define __HYPERVISOR_console_io           18
+#define __HYPERVISOR_physdev_op_compat    19 /* compat since 0x00030202 */
+#define __HYPERVISOR_grant_table_op       20
+#define __HYPERVISOR_vm_assist            21
+#define __HYPERVISOR_update_va_mapping_otherdomain 22
+#define __HYPERVISOR_iret                 23 /* x86 only */
+#define __HYPERVISOR_vcpu_op              24
+#define __HYPERVISOR_set_segment_base     25 /* x86/64 only */
+#define __HYPERVISOR_mmuext_op            26
+#define __HYPERVISOR_xsm_op               27
+#define __HYPERVISOR_nmi_op               28
+#define __HYPERVISOR_sched_op             29
+#define __HYPERVISOR_callback_op          30
+#define __HYPERVISOR_xenoprof_op          31
+#define __HYPERVISOR_event_channel_op     32
+#define __HYPERVISOR_physdev_op           33
+#define __HYPERVISOR_hvm_op               34
+#define __HYPERVISOR_sysctl               35
+#define __HYPERVISOR_domctl               36
+#define __HYPERVISOR_kexec_op             37
+#define __HYPERVISOR_tmem_op              38
+#define __HYPERVISOR_xc_reserved_op       39 /* reserved for XenClient */
+
+
+
+#define __HVC(imm16) .long ((0xE1400070 | (((imm16) & 0xFFF0) << 4) | ((imm16) & 
0x000F)) & 0xFFFFFFFF)
+
+#define XEN_IMM 0xEA1
+
+#define HYPERCALL_SIMPLE(hypercall)            \
+.globl HYPERVISOR_##hypercall;                 \
+.align 4,0x90;                                 \
+HYPERVISOR_##hypercall:                                \
+        mov r12, #__HYPERVISOR_##hypercall;    \
+        __HVC(XEN_IMM);                                \
+        mov pc, lr;
+
+#define _hypercall0 HYPERCALL_SIMPLE
+#define _hypercall1 HYPERCALL_SIMPLE
+#define _hypercall2 HYPERCALL_SIMPLE
+#define _hypercall3 HYPERCALL_SIMPLE
+#define _hypercall4 HYPERCALL_SIMPLE
+
+_hypercall1(set_trap_table);
+_hypercall4(mmu_update);
+_hypercall4(mmuext_op);
+_hypercall2(set_gdt);
+_hypercall2(stack_switch);
+_hypercall3(set_callbacks);
+_hypercall1(fpu_taskswitch);
+_hypercall2(sched_op);
+_hypercall1(set_timer_op);
+_hypercall2(set_debugreg);
+_hypercall1(get_debugreg);
+_hypercall2(update_descriptor);
+_hypercall2(memory_op);
+_hypercall2(multicall);
+_hypercall3(update_va_mapping);
+_hypercall2(event_channel_op);
+_hypercall2(xen_version);
+_hypercall3(console_io);
+_hypercall1(physdev_op);
+_hypercall3(grant_table_op);
+_hypercall4(update_va_mapping_otherdomain);
+_hypercall2(vm_assist);
+_hypercall3(vcpu_op);
+_hypercall2(set_segment_base);
+_hypercall2(nmi_op);
+_hypercall1(sysctl);
+_hypercall1(domctl);
+_hypercall2(hvm_op);
diff --git a/extras/mini-os/arch/arm/ldivmod.S 
b/extras/mini-os/arch/arm/ldivmod.S
new file mode 100644
index 0000000..7529826
--- /dev/null
+++ b/extras/mini-os/arch/arm/ldivmod.S
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2012 Andrew Turner
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+#define ENTRY_NP(symbol) \
+       .globl symbol;  \
+       symbol:
+
+#define END(symbol)
+
+/*
+ * These calculate:
+ * q = n / m
+ * With a remainer r.
+ *
+ * They take n in {r0, r1} and m in {r2, r3} then pass them into the
+ * helper function. The hepler functions return q in {r0, r1} as
+ * required by the API spec however r is returned on the stack. The
+ * ABI required us to return r in {r2, r3}.
+ *
+ * We need to allocate 8 bytes on the stack to store r, the link
+ * register, and a pointer to the space where the helper function
+ * will write r to. After returning from the helper fuinction we load
+ * the old link register and r from the stack and return.
+ */
+ENTRY_NP(__aeabi_ldivmod)
+       sub     sp, sp, #8      /* Space for the remainder */
+       stmfd   sp!, {sp, lr}   /* Save a pointer to the above space and lr */
+       bl      __kern_ldivmod
+       ldr     lr, [sp, #4]    /* Restore lr */
+       add     sp, sp, #8      /* Move sp to the remainder value */
+       ldmfd   sp!, {r2, r3}   /* Load the remainder */
+       mov     pc, lr
+END(__aeabi_ldivmod)
+
+ENTRY_NP(__aeabi_uldivmod)
+       sub     sp, sp, #8      /* Space for the remainder */
+       stmfd   sp!, {sp, lr}   /* Save a pointer to the above space and lr */
+       bl      __qdivrem
+       ldr     lr, [sp, #4]    /* Restore lr */
+       add     sp, sp, #8      /* Move sp to the remainder value */
+       ldmfd   sp!, {r2, r3}   /* Load the remainder */
+       mov     pc, lr
+END(__aeabi_uldivmod)
diff --git a/extras/mini-os/arch/arm/ldivmod_helper.c 
b/extras/mini-os/arch/arm/ldivmod_helper.c
new file mode 100644
index 0000000..f4dde48
--- /dev/null
+++ b/extras/mini-os/arch/arm/ldivmod_helper.c
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2012 Andrew Turner
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+#include <mini-os/types.h>
+
+u_quad_t __qdivrem(u_quad_t u, u_quad_t v, u_quad_t *rem);
+
+quad_t
+__divdi3(quad_t a, quad_t b)
+{
+        u_quad_t ua, ub, uq;
+        int neg;
+
+        if (a < 0)
+                ua = -(u_quad_t)a, neg = 1;
+        else
+                ua = a, neg = 0;
+        if (b < 0)
+                ub = -(u_quad_t)b, neg ^= 1;
+        else
+                ub = b;
+        uq = __qdivrem(ua, ub, (u_quad_t *)0);
+        return (neg ? -uq : uq);
+}
+
+/*
+ * Helper for __aeabi_ldivmod.
+ * TODO: __divdi3 calls __qdivrem. We should do the same and use the
+ * remainder value rather than re-calculating it.
+ */
+long long __kern_ldivmod(long long, long long, long long *);
+
+long long
+__kern_ldivmod(long long n, long long m, long long *rem)
+{
+       long long q;
+
+       q = __divdi3(n, m);     /* q = n / m */
+       *rem = n - m * q;
+
+       return q;
+}
diff --git a/extras/mini-os/arch/arm/minios-arm32.lds 
b/extras/mini-os/arch/arm/minios-arm32.lds
new file mode 100755
index 0000000..793f0de
--- /dev/null
+++ b/extras/mini-os/arch/arm/minios-arm32.lds
@@ -0,0 +1,73 @@
+OUTPUT_ARCH(arm)
+ENTRY(_start)
+SECTIONS
+{
+  . = 0x80008000;
+  _text = .;                   /* Text and read-only data */
+  .text : {
+       *(.text)
+       *(.gnu.warning)
+       } = 0x9090
+
+  _etext = .;                  /* End of text section */
+
+  .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 = .);
+
+  .ctors : {
+        __CTOR_LIST__ = .;
+        *(.ctors)
+       CONSTRUCTORS
+        LONG(0)
+        __CTOR_END__ = .;
+        }
+
+  .dtors : {
+        __DTOR_LIST__ = .;
+        *(.dtors)
+        LONG(0)
+        __DTOR_END__ = .;
+        }
+
+  .data : {                    /* Data */
+       *(.data)
+       }
+
+  _edata = .;                  /* End of data section */
+
+  __bss_start = .;             /* BSS */
+  .bss : {
+       *(.bss)
+        *(.app.bss)
+       }
+  _end = . ;
+
+  /* Sections to be discarded */
+  /DISCARD/ : {
+       *(.text.exit)
+       *(.data.exit)
+       *(.exitcall.exit)
+       }
+
+  /* Stabs debugging sections.  */
+  .stab 0 : { *(.stab) }
+  .stabstr 0 : { *(.stabstr) }
+  .stab.excl 0 : { *(.stab.excl) }
+  .stab.exclstr 0 : { *(.stab.exclstr) }
+  .stab.index 0 : { *(.stab.index) }
+  .stab.indexstr 0 : { *(.stab.indexstr) }
+  .comment 0 : { *(.comment) }
+}
diff --git a/extras/mini-os/arch/arm/mm.c b/extras/mini-os/arch/arm/mm.c
new file mode 100644
index 0000000..7e7ff06
--- /dev/null
+++ b/extras/mini-os/arch/arm/mm.c
@@ -0,0 +1,44 @@
+#include <console.h>
+#include <arm/arch_mm.h>
+
+#define PHYS_START (0x80008000 + (1000 * 4 * 1024))
+#define PHYS_SIZE (40*1024*1024)
+
+static void build_pagetable(unsigned long *start_pfn, unsigned long *max_pfn)
+{
+       // FIXME Create small pages descriptors here instead of the 1M 
superpages created earlier.
+       return;
+}
+
+unsigned long allocate_ondemand(unsigned long n, unsigned long alignment)
+{
+       // FIXME
+       BUG();
+}
+
+void arch_init_mm(unsigned long* start_pfn_p, unsigned long* max_pfn_p)
+{
+       printk("    _text: %p(VA)\n", &_text);
+       printk("    _etext: %p(VA)\n", &_etext);
+       printk("    _erodata: %p(VA)\n", &_erodata);
+       printk("    _edata: %p(VA)\n", &_edata);
+       printk("    stack start: %p(VA)\n", stack);
+       printk("    _end: %p(VA)\n", &_end);
+
+       // FIXME Get from dt!
+       *start_pfn_p = (((unsigned long)&_end) >> PAGE_SHIFT) + 1000;
+       *max_pfn_p = ((unsigned long)&_end + PHYS_SIZE) >> PAGE_SHIFT;
+
+       printk("    start_pfn: %lx\n", *start_pfn_p);
+       printk("    max_pfn: %lx\n", *max_pfn_p);
+
+       build_pagetable(start_pfn_p, max_pfn_p);
+}
+
+void arch_init_p2m(unsigned long max_pfn)
+{
+}
+
+void arch_init_demand_mapping_area(unsigned long cur_pfn)
+{
+}
diff --git a/extras/mini-os/arch/arm/qdivrem.c 
b/extras/mini-os/arch/arm/qdivrem.c
new file mode 100644
index 0000000..0ab5733
--- /dev/null
+++ b/extras/mini-os/arch/arm/qdivrem.c
@@ -0,0 +1,270 @@
+/*-
+ * Copyright (c) 1992, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This software was developed by the Computer Systems Engineering group
+ * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
+ * contributed to Berkeley.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <mini-os/types.h>
+
+/*
+ * Multiprecision divide.  This algorithm is from Knuth vol. 2 (2nd ed),
+ * section 4.3.1, pp. 257--259.
+ */
+
+#define        B       (1 << HALF_BITS)  /* digit base */
+
+/* Combine two `digits' to make a single two-digit number. */
+#define        COMBINE(a, b) (((u_long)(a) << HALF_BITS) | (b))
+
+/* select a type for digits in base B: use unsigned short if they fit */
+#if ULONG_MAX == 0xffffffff && USHRT_MAX >= 0xffff
+typedef unsigned short digit;
+#else
+typedef u_long digit;
+#endif
+
+/*
+ * Shift p[0]..p[len] left `sh' bits, ignoring any bits that
+ * `fall out' the left (there never will be any such anyway).
+ * We may assume len >= 0.  NOTE THAT THIS WRITES len+1 DIGITS.
+ */
+static void
+__shl(register digit *p, register int len, register int sh)
+{
+       register int i;
+
+       for (i = 0; i < len; i++)
+               p[i] = LHALF(p[i] << sh) | (p[i + 1] >> (HALF_BITS - sh));
+       p[i] = LHALF(p[i] << sh);
+}
+
+/*
+ * __qdivrem(u, v, rem) returns u/v and, optionally, sets *rem to u%v.
+ *
+ * We do this in base 2-sup-HALF_BITS, so that all intermediate products
+ * fit within u_long.  As a consequence, the maximum length dividend and
+ * divisor are 4 `digits' in this base (they are shorter if they have
+ * leading zeros).
+ */
+u_quad_t
+__qdivrem(u_quad_t uq, u_quad_t vq, u_quad_t *arq)
+{
+       union uu tmp;
+       digit *u, *v, *q;
+       register digit v1, v2;
+       u_long qhat, rhat, t;
+       int m, n, d, j, i;
+       digit uspace[5], vspace[5], qspace[5];
+
+       /*
+        * Take care of special cases: divide by zero, and u < v.
+        */
+       if (vq == 0) {
+               /* divide by zero. */
+               static volatile const unsigned int zero = 0;
+
+               tmp.ul[H] = tmp.ul[L] = 1 / zero;
+               if (arq)
+                       *arq = uq;
+               return (tmp.q);
+       }
+       if (uq < vq) {
+               if (arq)
+                       *arq = uq;
+               return (0);
+       }
+       u = &uspace[0];
+       v = &vspace[0];
+       q = &qspace[0];
+
+       /*
+        * Break dividend and divisor into digits in base B, then
+        * count leading zeros to determine m and n.  When done, we
+        * will have:
+        *      u = (u[1]u[2]...u[m+n]) sub B
+        *      v = (v[1]v[2]...v[n]) sub B
+        *      v[1] != 0
+        *      1 < n <= 4 (if n = 1, we use a different division algorithm)
+        *      m >= 0 (otherwise u < v, which we already checked)
+        *      m + n = 4
+        * and thus
+        *      m = 4 - n <= 2
+        */
+       tmp.uq = uq;
+       u[0] = 0;
+       u[1] = HHALF(tmp.ul[H]);
+       u[2] = LHALF(tmp.ul[H]);
+       u[3] = HHALF(tmp.ul[L]);
+       u[4] = LHALF(tmp.ul[L]);
+       tmp.uq = vq;
+       v[1] = HHALF(tmp.ul[H]);
+       v[2] = LHALF(tmp.ul[H]);
+       v[3] = HHALF(tmp.ul[L]);
+       v[4] = LHALF(tmp.ul[L]);
+       for (n = 4; v[1] == 0; v++) {
+               if (--n == 1) {
+                       u_long rbj;     /* r*B+u[j] (not root boy jim) */
+                       digit q1, q2, q3, q4;
+
+                       /*
+                        * Change of plan, per exercise 16.
+                        *      r = 0;
+                        *      for j = 1..4:
+                        *              q[j] = floor((r*B + u[j]) / v),
+                        *              r = (r*B + u[j]) % v;
+                        * We unroll this completely here.
+                        */
+                       t = v[2];       /* nonzero, by definition */
+                       q1 = u[1] / t;
+                       rbj = COMBINE(u[1] % t, u[2]);
+                       q2 = rbj / t;
+                       rbj = COMBINE(rbj % t, u[3]);
+                       q3 = rbj / t;
+                       rbj = COMBINE(rbj % t, u[4]);
+                       q4 = rbj / t;
+                       if (arq)
+                               *arq = rbj % t;
+                       tmp.ul[H] = COMBINE(q1, q2);
+                       tmp.ul[L] = COMBINE(q3, q4);
+                       return (tmp.q);
+               }
+       }
+
+       /*
+        * By adjusting q once we determine m, we can guarantee that
+        * there is a complete four-digit quotient at &qspace[1] when
+        * we finally stop.
+        */
+       for (m = 4 - n; u[1] == 0; u++)
+               m--;
+       for (i = 4 - m; --i >= 0;)
+               q[i] = 0;
+       q += 4 - m;
+
+       /*
+        * Here we run Program D, translated from MIX to C and acquiring
+        * a few minor changes.
+        *
+        * D1: choose multiplier 1 << d to ensure v[1] >= B/2.
+        */
+       d = 0;
+       for (t = v[1]; t < B / 2; t <<= 1)
+               d++;
+       if (d > 0) {
+               __shl(&u[0], m + n, d);             /* u <<= d */
+               __shl(&v[1], n - 1, d);             /* v <<= d */
+       }
+       /*
+        * D2: j = 0.
+        */
+       j = 0;
+       v1 = v[1];      /* for D3 -- note that v[1..n] are constant */
+       v2 = v[2];      /* for D3 */
+       do {
+               register digit uj0, uj1, uj2;
+
+               /*
+                * D3: Calculate qhat (\^q, in TeX notation).
+                * Let qhat = min((u[j]*B + u[j+1])/v[1], B-1), and
+                * let rhat = (u[j]*B + u[j+1]) mod v[1].
+                * While rhat < B and v[2]*qhat > rhat*B+u[j+2],
+                * decrement qhat and increase rhat correspondingly.
+                * Note that if rhat >= B, v[2]*qhat < rhat*B.
+                */
+               uj0 = u[j + 0]; /* for D3 only -- note that u[j+...] change */
+               uj1 = u[j + 1]; /* for D3 only */
+               uj2 = u[j + 2]; /* for D3 only */
+               if (uj0 == v1) {
+                       qhat = B;
+                       rhat = uj1;
+                       goto qhat_too_big;
+               } else {
+                       u_long nn = COMBINE(uj0, uj1);
+                       qhat = nn / v1;
+                       rhat = nn % v1;
+               }
+               while (v2 * qhat > COMBINE(rhat, uj2)) {
+       qhat_too_big:
+                       qhat--;
+                       if ((rhat += v1) >= B)
+                               break;
+               }
+               /*
+                * D4: Multiply and subtract.
+                * The variable `t' holds any borrows across the loop.
+                * We split this up so that we do not require v[0] = 0,
+                * and to eliminate a final special case.
+                */
+               for (t = 0, i = n; i > 0; i--) {
+                       t = u[i + j] - v[i] * qhat - t;
+                       u[i + j] = LHALF(t);
+                       t = (B - HHALF(t)) & (B - 1);
+               }
+               t = u[j] - t;
+               u[j] = LHALF(t);
+               /*
+                * D5: test remainder.
+                * There is a borrow if and only if HHALF(t) is nonzero;
+                * in that (rare) case, qhat was too large (by exactly 1).
+                * Fix it by adding v[1..n] to u[j..j+n].
+                */
+               if (HHALF(t)) {
+                       qhat--;
+                       for (t = 0, i = n; i > 0; i--) { /* D6: add back. */
+                               t += u[i + j] + v[i];
+                               u[i + j] = LHALF(t);
+                               t = HHALF(t);
+                       }
+                       u[j] = LHALF(u[j] + t);
+               }
+               q[j] = qhat;
+       } while (++j <= m);          /* D7: loop on j. */
+
+       /*
+        * If caller wants the remainder, we have to calculate it as
+        * u[m..m+n] >> d (this is at most n digits and thus fits in
+        * u[m+1..m+n], but we may need more source digits).
+        */
+       if (arq) {
+               if (d) {
+                       for (i = m + n; i > m; --i)
+                               u[i] = (u[i] >> d) |
+                                   LHALF(u[i - 1] << (HALF_BITS - d));
+                       u[i] = 0;
+               }
+               tmp.ul[H] = COMBINE(uspace[1], uspace[2]);
+               tmp.ul[L] = COMBINE(uspace[3], uspace[4]);
+               *arq = tmp.q;
+       }
+
+       tmp.ul[H] = COMBINE(qspace[1], qspace[2]);
+       tmp.ul[L] = COMBINE(qspace[3], qspace[4]);
+       return (tmp.q);
+}
diff --git a/extras/mini-os/arch/arm/sched.c b/extras/mini-os/arch/arm/sched.c
new file mode 100644
index 0000000..e490105
--- /dev/null
+++ b/extras/mini-os/arch/arm/sched.c
@@ -0,0 +1,32 @@
+#include <mini-os/sched.h>
+#include <mini-os/xmalloc.h>
+
+
+/* Architecture specific setup of thread creation */
+struct thread* arch_create_thread(char *name, void (*function)(void *),
+                                  void *data)
+{
+    struct thread *thread;
+
+    thread = xmalloc(struct thread);
+    /* We can't use lazy allocation here since the trap handler runs on the 
stack */
+    thread->stack = (char *)alloc_pages(STACK_SIZE_PAGE_ORDER);
+    thread->name = name;
+    printk("Thread \"%s\": pointer: 0x%lx, stack: 0x%lx\n", name, thread,
+            thread->stack);
+
+    thread->sp = (unsigned long)thread->stack + STACK_SIZE;
+    /* Save pointer to the thread on the stack, used by current macro */
+    *((unsigned long *)thread->stack) = (unsigned long)thread;
+
+    thread->ip = (unsigned long) function;
+    /* FIXME thread->r0 = (unsigned long)data; */
+
+    return thread;
+}
+
+void run_idle_thread(void)
+{
+       __asm__ __volatile__ ("mov sp, %0; mov pc, %1"::"r"(idle_thread->sp), 
"r"(idle_thread->ip));
+       /* Never arrive here! */
+}
diff --git a/extras/mini-os/arch/arm/setup.c b/extras/mini-os/arch/arm/setup.c
new file mode 100644
index 0000000..f0b2f47
--- /dev/null
+++ b/extras/mini-os/arch/arm/setup.c
@@ -0,0 +1,55 @@
+#include <mini-os/os.h>
+#include <xen/xen.h>
+#include <xen/memory.h>
+#include <hypervisor.h>
+#include <arm/arch_mm.h>
+
+/*
+ * This structure contains start-of-day info, such as pagetable base pointer,
+ * address of the shared_info structure, and things like that.
+ */
+union start_info_union start_info_union;
+
+/*
+ * Shared page for communicating with the hypervisor.
+ * Events flags go here, for example.
+ */
+shared_info_t *HYPERVISOR_shared_info;
+
+extern char shared_info_page[PAGE_SIZE];
+
+void start_kernel(void);
+
+/*
+ * INITIAL C ENTRY POINT.
+ */
+void arch_init(void *dtb_pointer)
+{
+    struct xen_add_to_physmap xatp;
+
+    memset(&__bss_start, 0, &_end - &__bss_start);
+
+    printk("dtb_pointer : %x\n", dtb_pointer);
+
+    /* Map shared_info page */
+       xatp.domid = DOMID_SELF;
+       xatp.idx = 0;
+       xatp.space = XENMAPSPACE_shared_info;
+       xatp.gpfn = virt_to_pfn(shared_info_page);
+       if (HYPERVISOR_memory_op(XENMEM_add_to_physmap, &xatp) != 0)
+               BUG();
+       HYPERVISOR_shared_info = (struct shared_info *)shared_info_page;
+
+       start_kernel();
+}
+
+void
+arch_fini(void)
+{
+
+}
+
+void
+arch_do_exit(void)
+{
+}
diff --git a/extras/mini-os/arch/arm/time.c b/extras/mini-os/arch/arm/time.c
new file mode 100644
index 0000000..6dba1fe
--- /dev/null
+++ b/extras/mini-os/arch/arm/time.c
@@ -0,0 +1,232 @@
+#include <mini-os/os.h>
+#include <mini-os/hypervisor.h>
+#include <mini-os/events.h>
+#include <mini-os/traps.h>
+#include <mini-os/types.h>
+#include <mini-os/time.h>
+#include <mini-os/lib.h>
+
+//#define VTIMER_DEBUG
+#ifdef VTIMER_DEBUG
+#define DEBUG(_f, _a...) \
+    printk("MINI_OS(file=vtimer.c, line=%d) " _f , __LINE__, ## _a)
+#else
+#define DEBUG(_f, _a...)    ((void)0)
+#endif
+
+
+/************************************************************************
+ * Time functions
+ *************************************************************************/
+
+/* These are peridically updated in shared_info, and then copied here. */
+struct shadow_time_info {
+       uint64_t tsc_timestamp;     /* TSC at last update of time vals.  */
+       uint64_t system_timestamp;  /* Time, in nanosecs, since boot.    */
+       uint32_t tsc_to_nsec_mul;
+       uint32_t tsc_to_usec_mul;
+       int tsc_shift;
+       uint32_t version;
+};
+static struct timespec shadow_ts;
+static uint32_t shadow_ts_version;
+
+static struct shadow_time_info shadow;
+
+#define HANDLE_USEC_OVERFLOW(_tv)          \
+    do {                                   \
+        while ( (_tv)->tv_usec >= 1000000 ) \
+        {                                  \
+            (_tv)->tv_usec -= 1000000;      \
+            (_tv)->tv_sec++;                \
+        }                                  \
+    } while ( 0 )
+
+static inline int time_values_up_to_date(void)
+{
+       struct vcpu_time_info *src = &HYPERVISOR_shared_info->vcpu_info[0].time;
+
+       return (shadow.version == src->version);
+}
+
+
+/*
+ * Scale a 64-bit delta by scaling and multiplying by a 32-bit fraction,
+ * yielding a 64-bit result.
+ */
+static inline uint64_t scale_delta(uint64_t delta, uint32_t mul_frac, int 
shift)
+{
+       BUG();
+       return 0;
+}
+
+
+static unsigned long get_nsec_offset(void)
+{
+       return 0;
+#if FIXME
+       uint64_t now, delta;
+       rdtscll(now);
+       delta = now - shadow.tsc_timestamp;
+       return scale_delta(delta, shadow.tsc_to_nsec_mul, shadow.tsc_shift);
+#endif
+}
+
+
+static void get_time_values_from_xen(void)
+{
+       struct vcpu_time_info    *src = 
&HYPERVISOR_shared_info->vcpu_info[0].time;
+
+       do {
+               shadow.version = src->version;
+               rmb();
+               shadow.tsc_timestamp     = src->tsc_timestamp;
+               shadow.system_timestamp  = src->system_time;
+               shadow.tsc_to_nsec_mul   = src->tsc_to_system_mul;
+               shadow.tsc_shift         = src->tsc_shift;
+               rmb();
+       }
+       while ((src->version & 1) | (shadow.version ^ src->version));
+
+       shadow.tsc_to_usec_mul = shadow.tsc_to_nsec_mul / 1000;
+}
+
+
+
+
+/* monotonic_clock(): returns # of nanoseconds passed since time_init()
+ *             Note: This function is required to return accurate
+ *             time even in the absence of multiple timer ticks.
+ */
+uint64_t monotonic_clock(void)
+{
+       uint64_t time;
+       uint32_t local_time_version;
+
+       do {
+               local_time_version = shadow.version;
+               rmb();
+               time = shadow.system_timestamp + get_nsec_offset();
+        if (!time_values_up_to_date())
+                       get_time_values_from_xen();
+               rmb();
+       } while (local_time_version != shadow.version);
+
+       return time;
+}
+
+static void update_wallclock(void)
+{
+       shared_info_t *s = HYPERVISOR_shared_info;
+
+       do {
+               shadow_ts_version = s->wc_version;
+               rmb();
+               shadow_ts.tv_sec  = s->wc_sec;
+               shadow_ts.tv_nsec = s->wc_nsec;
+               rmb();
+       }
+       while ((s->wc_version & 1) | (shadow_ts_version ^ s->wc_version));
+}
+
+
+int gettimeofday(struct timeval *tv, void *tz)
+{
+    uint64_t nsec = monotonic_clock();
+    nsec += shadow_ts.tv_nsec;
+
+
+    tv->tv_sec = shadow_ts.tv_sec;
+    tv->tv_sec += NSEC_TO_SEC(nsec);
+    tv->tv_usec = NSEC_TO_USEC(nsec % 1000000000UL);
+
+    return 0;
+}
+
+
+void block_domain(s_time_t until)
+{
+    struct timeval tv;
+    gettimeofday(&tv, NULL);
+    ASSERT(irqs_disabled());
+    if(monotonic_clock() < until)
+    {
+        HYPERVISOR_set_timer_op(until);
+        HYPERVISOR_sched_op(SCHEDOP_block, 0);
+        local_irq_disable();
+    }
+}
+
+
+/*
+ * Just a dummy
+ */
+void timer_handler(evtchn_port_t port, struct pt_regs *regs, void *ign)
+{
+       DEBUG("Timer kick\n");
+    get_time_values_from_xen();
+       update_wallclock();
+}
+
+#define VTIMER_TICK 0x10000000
+void increment_vtimer_compare(uint64_t inc) {
+       uint32_t x, y;
+       uint64_t value;
+       __asm__ __volatile__("mrrc p15, 1, %0, %1, c14\n"
+                       "isb":"=r"(x), "=r"(y));
+
+       // CompareValue = Counter + VTIMER_TICK
+       value = (0xFFFFFFFFFFFFFFFFULL & x) | ((0xFFFFFFFFFFFFFFFFULL & y) << 
32);
+       DEBUG("Counter: %llx(x=%x and y=%x)\n", value, x, y);
+       value += inc;
+       DEBUG("New CompareValue : %llx\n", value);
+       x = 0xFFFFFFFFULL & value;
+       y = (value >> 32) & 0xFFFFFFFF;
+
+       __asm__ __volatile__("mcrr p15, 3, %0, %1, c14\n"
+                       "isb"::"r"(x), "r"(y));
+
+       __asm__ __volatile__("mov %0, #0x1\n"
+                               "mcr p15, 0, %0, c14, c3, 1\n" /* Enable timer 
and unmask the output signal */
+                               "isb":"=r"(x));
+}
+
+static inline void enable_virtual_timer(void) {
+#if FIXME
+       uint32_t x, y;
+       uint64_t value;
+
+       __asm__ __volatile__("ldr %0, =0xffffffff\n"
+                       "ldr %1, =0xffffffff\n"
+                       "dsb\n"
+                       "mcrr p15, 3, %0, %1, c14\n" /* set CompareValue to 
0x0000ffff 0000ffff */
+                       "isb\n"
+                       "mov %0, #0x1\n"
+                       "mcr p15, 0, %0, c14, c3, 1\n" /* Enable timer and 
unmask the output signal */
+                       "isb":"=r"(x), "=r"(y));
+#else
+       increment_vtimer_compare(VTIMER_TICK);
+#endif
+}
+
+evtchn_port_t timer_port = -1;
+void arch_init_time(void)
+{
+       // FIXME: VIRQ_TIMER isn't supported under ARM, use ARM Generic Timer 
instead.
+    printk("Initialising timer interface\n");
+    timer_port = bind_virq(VIRQ_TIMER, (evtchn_handler_t)timer_handler, 0);
+    if(timer_port == -1)
+               BUG();
+    unmask_evtchn(timer_port);
+
+    enable_virtual_timer();
+}
+
+void arch_fini_time(void)
+{
+       if(timer_port != -1)
+       {
+               mask_evtchn(timer_port);
+               unbind_evtchn(timer_port);
+       }
+}
diff --git a/extras/mini-os/arch/arm/xenbus.c b/extras/mini-os/arch/arm/xenbus.c
new file mode 100644
index 0000000..76feabc
--- /dev/null
+++ b/extras/mini-os/arch/arm/xenbus.c
@@ -0,0 +1,36 @@
+#include <mini-os/os.h>
+#include <mini-os/mm.h>
+#include <xen/hvm/params.h>
+#include <xen/io/xs_wire.h>
+#include <mini-os/hypervisor.h>
+
+static inline int hvm_get_parameter(int idx, uint64_t *value)
+{
+       struct xen_hvm_param xhv;
+       int ret;
+
+       xhv.domid = DOMID_SELF;
+       xhv.index = idx;
+       ret = HYPERVISOR_hvm_op(HVMOP_get_param, &xhv);
+       if (ret < 0) {
+               BUG();
+       }
+       *value = xhv.value;
+       return ret;
+}
+
+void arch_init_xenbus(struct xenstore_domain_interface **xenstore_buf, 
uint32_t *store_evtchn) {
+       uint64_t value;
+       uint64_t xenstore_pfn;
+
+       if (hvm_get_parameter(HVM_PARAM_STORE_EVTCHN, &value))
+               BUG();
+
+       *store_evtchn = (int)value;
+
+       if(hvm_get_parameter(HVM_PARAM_STORE_PFN, &value))
+               BUG();
+       xenstore_pfn = (unsigned long)value;
+
+       *xenstore_buf = pfn_to_virt(xenstore_pfn);
+}
diff --git a/extras/mini-os/arch/x86/events.c b/extras/mini-os/arch/x86/events.c
new file mode 100644
index 0000000..87f8b77
--- /dev/null
+++ b/extras/mini-os/arch/x86/events.c
@@ -0,0 +1,28 @@
+#include <mini-os/os.h>
+#include <mini-os/mm.h>
+
+#if defined(__x86_64__)
+char irqstack[2 * STACK_SIZE];
+
+static struct pda
+{
+    int irqcount;       /* offset 0 (used in x86_64.S) */
+    char *irqstackptr;  /*        8 */
+} cpu0_pda;
+#endif
+
+void arch_init_events(void) {
+#if defined(__x86_64__)
+    asm volatile("movl %0,%%fs ; movl %0,%%gs" :: "r" (0));
+    wrmsrl(0xc0000101, &cpu0_pda); /* 0xc0000101 is MSR_GS_BASE */
+    cpu0_pda.irqcount = -1;
+    cpu0_pda.irqstackptr = (void*) (((unsigned long)irqstack + 2 * STACK_SIZE)
+                                    & ~(STACK_SIZE - 1));
+#endif
+}
+
+void arch_fini_events(void) {
+#if defined(__x86_64__)
+    wrmsrl(0xc0000101, NULL); /* 0xc0000101 is MSR_GS_BASE */
+#endif
+}
diff --git a/extras/mini-os/arch/x86/setup.c b/extras/mini-os/arch/x86/setup.c
index 54046d3..6bb6d4b 100644
--- a/extras/mini-os/arch/x86/setup.c
+++ b/extras/mini-os/arch/x86/setup.c
@@ -28,6 +28,7 @@

  #include <mini-os/os.h>
  #include <mini-os/lib.h> /* for printk, memcpy */
+#include <xen/xen.h>

  /*
   * Shared page for communicating with the hypervisor.
@@ -87,14 +88,40 @@ static inline void sse_init(void) {
  #define sse_init()
  #endif

+
+void start_kernel(void);
+
+/*
+ * INITIAL C ENTRY POINT.
+ */
  void
  arch_init(start_info_t *si)
  {
+    static char hello[] = "Bootstrapping...\n";
+
+    (void)HYPERVISOR_console_io(CONSOLEIO_write, strlen(hello), hello);
+
+    trap_init();
+
+    /* print out some useful information  */
+    printk("Xen Minimal OS!\n");
+    printk("  start_info: %p(VA)\n", si);
+    printk("    nr_pages: 0x%lx\n", si->nr_pages);
+    printk("  shared_inf: 0x%08lx(MA)\n", si->shared_info);
+    printk("     pt_base: %p(VA)\n", (void *)si->pt_base);
+    printk("nr_pt_frames: 0x%lx\n", si->nr_pt_frames);
+    printk("    mfn_list: %p(VA)\n", (void *)si->mfn_list);
+    printk("   mod_start: 0x%lx(VA)\n", si->mod_start);
+    printk("     mod_len: %lu\n", si->mod_len);
+    printk("       flags: 0x%x\n", (unsigned int)si->flags);
+    printk("    cmd_line: %s\n",
+           si->cmd_line ? (const char *)si->cmd_line : "NULL");
+
        /*Initialize floating point unit */
-        fpu_init();
+       fpu_init();

-        /* Initialize SSE */
-        sse_init();
+       /* Initialize SSE */
+       sse_init();

        /* Copy the start_info struct to a globally-accessible area. */
        /* WARN: don't do printk before here, it uses information from
@@ -118,12 +145,15 @@ arch_init(start_info_t *si)
                (unsigned long)failsafe_callback, 0);
  #endif

-
+       start_kernel();
  }

  void
  arch_fini(void)
  {
+       /* Reset traps */
+       trap_fini();
+
  #ifdef __i386__
        HYPERVISOR_set_callbacks(0, 0, 0, 0);
  #else
@@ -132,9 +162,7 @@ arch_fini(void)
  }

  void
-arch_print_info(void)
+arch_do_exit(void)
  {
-       printk("  stack:      %p-%p\n", stack, stack + sizeof(stack));
+       stack_walk();
  }
-
-
diff --git a/extras/mini-os/arch/x86/time.c b/extras/mini-os/arch/x86/time.c
index 2c8d033..c57ee55 100644
--- a/extras/mini-os/arch/x86/time.c
+++ b/extras/mini-os/arch/x86/time.c
@@ -223,14 +223,14 @@ static void timer_handler(evtchn_port_t ev, struct 
pt_regs *regs, void *ign)


  static evtchn_port_t port;
-void init_time(void)
+void arch_init_time(void)
  {
      printk("Initialising timer interface\n");
      port = bind_virq(VIRQ_TIMER, &timer_handler, NULL);
      unmask_evtchn(port);
  }

-void fini_time(void)
+void arch_fini_time(void)
  {
      /* Clear any pending timer */
      HYPERVISOR_set_timer_op(0);
diff --git a/extras/mini-os/arch/x86/x86_32.S b/extras/mini-os/arch/x86/x86_32.S
index fb3e30a..b9aa392 100644
--- a/extras/mini-os/arch/x86/x86_32.S
+++ b/extras/mini-os/arch/x86/x86_32.S
@@ -20,7 +20,7 @@ _start:
          lss stack_start,%esp
          andl $(~(__STACK_SIZE-1)), %esp
          push %esi
-        call start_kernel
+        call arch_init

  stack_start:
        .long stack+(2*__STACK_SIZE), __KERNEL_SS
diff --git a/extras/mini-os/arch/x86/x86_64.S b/extras/mini-os/arch/x86/x86_64.S
index f022eb3..df3469e 100644
--- a/extras/mini-os/arch/x86/x86_64.S
+++ b/extras/mini-os/arch/x86/x86_64.S
@@ -21,7 +21,7 @@ _start:
          movq stack_start(%rip),%rsp
          andq $(~(__STACK_SIZE-1)), %rsp
          movq %rsi,%rdi
-        call start_kernel
+        call arch_init

  stack_start:
          .quad stack+(2*__STACK_SIZE)
diff --git a/extras/mini-os/arch/x86/xenbus.c b/extras/mini-os/arch/x86/xenbus.c
new file mode 100644
index 0000000..5cda78d
--- /dev/null
+++ b/extras/mini-os/arch/x86/xenbus.c
@@ -0,0 +1,10 @@
+#include <mini-os/os.h>
+#include <mini-os/mm.h>
+#include <mini-os/xmalloc.h>
+#include <xen/xen.h>
+#include <xen/io/xs_wire.h>
+
+void arch_init_xenbus(struct xenstore_domain_interface **xenstore_buf, 
uint32_t *store_evtchn) {
+    *xenstore_buf = mfn_to_virt(start_info.store_mfn);
+    *store_evtchn = start_info.store_evtchn;
+}
diff --git a/extras/mini-os/console/console.c b/extras/mini-os/console/console.c
index 5538bd4..c08fea9 100644
--- a/extras/mini-os/console/console.c
+++ b/extras/mini-os/console/console.c
@@ -157,7 +157,9 @@ void xprintk(const char *fmt, ...)
  void init_console(void)
  {
      printk("Initialising console ... ");
+#ifndef __arm__
      xencons_ring_init();
+#endif
      console_initialised = 1;
      /* This is also required to notify the daemon */
      printk("done.\n");
diff --git a/extras/mini-os/drivers/gic.c b/extras/mini-os/drivers/gic.c
new file mode 100644
index 0000000..14301ae
--- /dev/null
+++ b/extras/mini-os/drivers/gic.c
@@ -0,0 +1,179 @@
+// ARM GIC implementation
+
+#include <mini-os/os.h>
+#include <mini-os/hypervisor.h>
+
+//#define VGIC_DEBUG
+#ifdef VGIC_DEBUG
+#define DEBUG(_f, _a...) \
+    DEBUG("MINI_OS(file=vgic.c, line=%d) " _f , __LINE__, ## _a)
+#else
+#define DEBUG(_f, _a...)    ((void)0)
+#endif
+
+extern unsigned long IRQ_handler;
+
+struct gic {
+       volatile char *gicd_base;
+       volatile char *gicc_base;
+};
+
+static struct gic gic;
+
+// Distributor Interface
+#define GICD_CTLR              0x0
+#define GICD_ISENABLER 0x100
+#define GICD_PRIORITY  0x400
+#define GICD_ITARGETSR 0x800
+#define GICD_ICFGR             0xC00
+
+// CPU Interface
+#define GICC_CTLR      0x0
+#define GICC_PMR       0x4
+#define GICC_IAR       0xc
+#define GICC_EOIR      0x10
+#define GICC_HPPIR     0x18
+
+#define gicd(gic, offset) ((gic)->gicd_base + (offset))
+#define gicc(gic, offset) ((gic)->gicc_base + (offset))
+
+#define REG(addr) ((uint32_t *)(addr))
+
+static inline uint32_t REG_READ32(volatile uint32_t *addr)
+{
+       uint32_t value;
+       __asm__ __volatile__("ldr %0, [%1]":"=&r"(value):"r"(addr));
+       rmb();
+       return value;
+}
+
+static inline void REG_WRITE32(volatile uint32_t *addr, unsigned int value)
+{
+       __asm__ __volatile__("str %0, [%1]"::"r"(value), "r"(addr));
+       wmb();
+}
+
+static void gic_set_priority(struct gic *gic, unsigned char irq_number, 
unsigned char priority)
+{
+       uint32_t value;
+       value = REG_READ32(REG(gicd(gic, GICD_PRIORITY)) + irq_number);
+       value &= ~(0xff << (8 * (irq_number & 0x3))); // set priority to '0'
+       value |= priority << (8 * (irq_number & 0x3)); // add our priority
+       REG_WRITE32(REG(gicd(gic, GICD_PRIORITY)) + irq_number, value);
+}
+
+static void gic_route_interrupt(struct gic *gic, unsigned char irq_number, 
unsigned char cpu_set)
+{
+       uint32_t value;
+       value = REG_READ32(REG(gicd(gic, GICD_ITARGETSR)) + irq_number);
+       value &= ~(0xff << (8 * (irq_number & 0x3))); // set priority to '0'
+       value |= cpu_set << (8 * (irq_number & 0x3)); // add our priority
+       REG_WRITE32(REG(gicd(gic, GICD_ITARGETSR)) + irq_number, value);
+}
+
+static void gic_enable_interrupt(struct gic *gic, unsigned char irq_number,
+               unsigned char cpu_set, unsigned char level_sensitive, unsigned 
char ppi)
+{
+       void *set_enable_reg;
+       void *cfg_reg;
+
+       // set priority
+       gic_set_priority(gic, irq_number, 0x0);
+
+       // set target cpus for this interrupt
+       gic_route_interrupt(gic, irq_number, cpu_set);
+
+       // set level/edge triggered
+       cfg_reg = (void *)gicd(gic, GICD_ICFGR);
+       level_sensitive ? clear_bit((irq_number * 2) + 1, cfg_reg) : 
set_bit((irq_number * 2) + 1, cfg_reg);
+       if(ppi)
+               clear_bit((irq_number * 2), cfg_reg);
+
+       wmb();
+
+       // enable forwarding interrupt from distributor to cpu interface
+       set_enable_reg = (void *)gicd(gic, GICD_ISENABLER);
+       set_bit(irq_number, set_enable_reg);
+       wmb();
+}
+
+static void gic_enable_interrupts(struct gic *gic)
+{
+       // Global enable forwarding interrupts from distributor to cpu interface
+       REG_WRITE32(REG(gicd(gic, GICD_CTLR)), 0x00000001);
+
+       // Global enable signalling of interrupt from the cpu interface
+       REG_WRITE32(REG(gicc(gic, GICC_CTLR)), 0x00000001);
+}
+
+static void gic_disable_interrupts(struct gic *gic)
+{
+       // Global disable signalling of interrupt from the cpu interface
+       REG_WRITE32(REG(gicc(gic, GICC_CTLR)), 0x00000000);
+
+       // Global disable forwarding interrupts from distributor to cpu 
interface
+       REG_WRITE32(REG(gicd(gic, GICD_CTLR)), 0x00000000);
+}
+
+static void gic_cpu_set_priority(struct gic *gic, char priority)
+{
+       REG_WRITE32(REG(gicc(gic, GICC_PMR)), priority & 0x000000FF);
+}
+
+static void gic_set_handler(unsigned long gic_handler) {
+       IRQ_handler = gic_handler;
+}
+
+static unsigned long gic_readiar(struct gic *gic) {
+       return REG_READ32(REG(gicc(gic, GICC_IAR))) & 0x000003FF; // Interrupt 
ID
+}
+
+static void gic_eoir(struct gic *gic, uint32_t irq) {
+       REG_WRITE32(REG(gicc(gic, GICC_EOIR)), irq & 0x000003FF);
+}
+
+//FIXME Get event_irq from dt
+#define EVENTS_IRQ 31
+#define VIRTUALTIMER_IRQ 27
+
+//FIXME Move to a header file
+#define VTIMER_TICK 0x6000000
+void timer_handler(evtchn_port_t port, struct pt_regs *regs, void *ign);
+void increment_vtimer_compare(uint64_t inc);
+
+static void gic_handler(void) {
+       unsigned int irq = gic_readiar(&gic);
+
+       DEBUG("IRQ received : %i\n", irq);
+       switch(irq) {
+       case EVENTS_IRQ:
+               do_hypervisor_callback(NULL);
+               break;
+       case VIRTUALTIMER_IRQ:
+               timer_handler(0, NULL, 0);
+               increment_vtimer_compare(VTIMER_TICK);
+               break;
+       default:
+               DEBUG("Unhandled irq\n");
+               break;
+       }
+
+       DEBUG("EIRQ\n");
+
+       gic_eoir(&gic, irq);
+}
+
+void gic_init(void) {
+       // FIXME Get from dt!
+       gic.gicd_base = (char *)0x2c001000ULL;
+       gic.gicc_base = (char *)0x2c002000ULL;
+       wmb();
+
+       gic_set_handler((unsigned long)gic_handler);
+
+       gic_disable_interrupts(&gic);
+       gic_cpu_set_priority(&gic, 0xff);
+       gic_enable_interrupt(&gic, EVENTS_IRQ /* interrupt number */, 0x1 
/*cpu_set*/, 1 /*level_sensitive*/, 0 /* ppi */);
+       gic_enable_interrupt(&gic, VIRTUALTIMER_IRQ /* interrupt number */, 0x1 
/*cpu_set*/, 1 /*level_sensitive*/, 1 /* ppi */);
+       gic_enable_interrupts(&gic);
+}
diff --git a/extras/mini-os/events.c b/extras/mini-os/events.c
index 2da9b01..84a30a3 100644
--- a/extras/mini-os/events.c
+++ b/extras/mini-os/events.c
@@ -47,9 +47,11 @@ void unbind_all_ports(void)

      for ( i = 0; i < NR_EVS; i++ )
      {
+#ifndef __arm__
          if ( i == start_info.console.domU.evtchn ||
               i == start_info.store_evtchn)
              continue;
+#endif

          if ( test_and_clear_bit(i, bound_ports) )
          {
@@ -167,44 +169,30 @@ evtchn_port_t bind_pirq(uint32_t pirq, int will_share,
        return op.port;
  }

-#if defined(__x86_64__)
-char irqstack[2 * STACK_SIZE];
-
-static struct pda
-{
-    int irqcount;       /* offset 0 (used in x86_64.S) */
-    char *irqstackptr;  /*        8 */
-} cpu0_pda;
-#endif
-
+void arch_init_events(void);
  /*
   * Initially all events are without a handler and disabled
   */
  void init_events(void)
  {
      int i;
-#if defined(__x86_64__)
-    asm volatile("movl %0,%%fs ; movl %0,%%gs" :: "r" (0));
-    wrmsrl(0xc0000101, &cpu0_pda); /* 0xc0000101 is MSR_GS_BASE */
-    cpu0_pda.irqcount = -1;
-    cpu0_pda.irqstackptr = (void*) (((unsigned long)irqstack + 2 * STACK_SIZE)
-                                    & ~(STACK_SIZE - 1));
-#endif
+
      /* initialize event handler */
      for ( i = 0; i < NR_EVS; i++ )
        {
          ev_actions[i].handler = default_handler;
          mask_evtchn(i);
      }
+
+    arch_init_events();
  }

+void arch_fini_events(void);
  void fini_events(void)
  {
      /* Dealloc all events */
      unbind_all_ports();
-#if defined(__x86_64__)
-    wrmsrl(0xc0000101, NULL); /* 0xc0000101 is MSR_GS_BASE */
-#endif
+    arch_fini_events();
  }

  void default_handler(evtchn_port_t port, struct pt_regs *regs, void *ignore)
@@ -262,7 +250,8 @@ int evtchn_bind_interdomain(domid_t pal, evtchn_port_t 
remote_port,

  int evtchn_get_peercontext(evtchn_port_t local_port, char *ctx, int size)
  {
-    int rc;
+    int rc = 0;
+#ifndef __arm__
      uint32_t sid;
      struct xen_flask_op op;
      op.cmd = FLASK_GET_PEER_SID;
@@ -277,6 +266,7 @@ int evtchn_get_peercontext(evtchn_port_t local_port, char 
*ctx, int size)
      op.u.sid_context.size = size;
      set_xen_guest_handle(op.u.sid_context.context, ctx);
      rc = _hypercall1(int, xsm_op, &op);
+#endif
      return rc;
  }

diff --git a/extras/mini-os/gntmap.c b/extras/mini-os/gntmap.c
index 7eb69be..abfbd29 100644
--- a/extras/mini-os/gntmap.c
+++ b/extras/mini-os/gntmap.c
@@ -37,6 +37,7 @@
  #include <xen/grant_table.h>
  #include <inttypes.h>
  #include <mini-os/gntmap.h>
+#include <mini-os/hypervisor.h>

  //#define GNTMAP_DEBUG
  #ifdef GNTMAP_DEBUG
diff --git a/extras/mini-os/gnttab.c b/extras/mini-os/gnttab.c
index 2f1b3d7..404d72c 100644
--- a/extras/mini-os/gnttab.c
+++ b/extras/mini-os/gnttab.c
@@ -19,6 +19,7 @@
  #include <mini-os/mm.h>
  #include <mini-os/gnttab.h>
  #include <mini-os/semaphore.h>
+#include <mini-os/hypervisor.h>

  #define NR_RESERVED_ENTRIES 8

diff --git a/extras/mini-os/hypervisor.c b/extras/mini-os/hypervisor.c
index b4688a0..9c79d5d 100644
--- a/extras/mini-os/hypervisor.c
+++ b/extras/mini-os/hypervisor.c
@@ -71,23 +71,6 @@ void do_hypervisor_callback(struct pt_regs *regs)
      in_callback = 0;
  }

-void force_evtchn_callback(void)
-{
-    int save;
-    vcpu_info_t *vcpu;
-    vcpu = &HYPERVISOR_shared_info->vcpu_info[smp_processor_id()];
-    save = vcpu->evtchn_upcall_mask;
-
-    while (vcpu->evtchn_upcall_pending) {
-        vcpu->evtchn_upcall_mask = 1;
-        barrier();
-        do_hypervisor_callback(NULL);
-        barrier();
-        vcpu->evtchn_upcall_mask = save;
-        barrier();
-    };
-}
-
  inline void mask_evtchn(uint32_t port)
  {
      shared_info_t *s = HYPERVISOR_shared_info;
@@ -110,8 +93,7 @@ inline void unmask_evtchn(uint32_t port)
                &vcpu_info->evtchn_pending_sel) )
      {
          vcpu_info->evtchn_upcall_pending = 1;
-        if ( !vcpu_info->evtchn_upcall_mask )
-            force_evtchn_callback();
+        force_evtchn_callback();
      }
  }

diff --git a/extras/mini-os/include/arm/arch_limits.h 
b/extras/mini-os/include/arm/arch_limits.h
new file mode 100644
index 0000000..bae99e1
--- /dev/null
+++ b/extras/mini-os/include/arm/arch_limits.h
@@ -0,0 +1,9 @@
+#ifndef __ARCH_LIMITS_H__
+#define __ARCH_LIMITS_H__
+
+#include <mm.h>
+
+#define __STACK_SIZE_PAGE_ORDER  2
+#define __STACK_SIZE (4 * PAGE_SIZE)
+
+#endif
diff --git a/extras/mini-os/include/arm/arch_mm.h 
b/extras/mini-os/include/arm/arch_mm.h
new file mode 100644
index 0000000..9b2cc03
--- /dev/null
+++ b/extras/mini-os/include/arm/arch_mm.h
@@ -0,0 +1,37 @@
+#ifndef _ARCH_MM_H_
+#define _ARCH_MM_H_
+
+extern char _text, _etext, _erodata, _edata, _end, __bss_start;
+extern char stack[];
+
+#define PAGE_SHIFT             12
+#define PAGE_SIZE              (1 << PAGE_SHIFT)
+#define PAGE_MASK       (~(PAGE_SIZE-1))
+
+#define L1_PAGETABLE_SHIFT      12
+
+#if 0
+#define VIRT_START                 ((unsigned long)&_text)
+#else
+#define VIRT_START                 ((unsigned long)0)
+#endif
+
+#define to_phys(x)                 ((unsigned long)(x)-VIRT_START)
+#define to_virt(x)                 ((void *)((unsigned long)(x)+VIRT_START))
+
+#define PFN_UP(x)      (((x) + PAGE_SIZE-1) >> L1_PAGETABLE_SHIFT)
+#define PFN_DOWN(x)    ((x) >> L1_PAGETABLE_SHIFT)
+#define PFN_PHYS(x)    ((uint64_t)(x) << L1_PAGETABLE_SHIFT)
+#define PHYS_PFN(x)    ((x) >> L1_PAGETABLE_SHIFT)
+
+#define virt_to_pfn(_virt)         (PFN_DOWN(to_phys(_virt)))
+#define virt_to_mfn(_virt)         (0)
+#define mach_to_virt(_mach)        (0)
+#define virt_to_mach(_virt)        (0)
+#define mfn_to_virt(_mfn)          (0)
+#define pfn_to_virt(_pfn)          (to_virt(PFN_PHYS(_pfn)))
+
+// FIXME
+#define map_frames(f, n) (NULL)
+
+#endif
diff --git a/extras/mini-os/include/arm/arch_sched.h 
b/extras/mini-os/include/arm/arch_sched.h
new file mode 100644
index 0000000..31d9071
--- /dev/null
+++ b/extras/mini-os/include/arm/arch_sched.h
@@ -0,0 +1,22 @@
+
+#ifndef __ARCH_SCHED_H__
+#define __ARCH_SCHED_H__
+
+#include "arch_limits.h"
+
+static inline struct thread* get_current(void)
+{
+   struct thread **current;
+   unsigned long sp;
+   __asm__ __volatile__ ("mov %0, sp":"=r"(sp));
+       current = (void *)(unsigned long)(sp & ~(__STACK_SIZE-1));
+       return *current;
+}
+
+
+extern void __arch_switch_threads(unsigned long *prevctx, unsigned long 
*nextctx);
+
+#define arch_switch_threads(prev,next) __arch_switch_threads(&(prev)->sp, 
&(next)->sp)
+
+
+#endif /* __ARCH_SCHED_H__ */
diff --git a/extras/mini-os/include/arm/arch_spinlock.h 
b/extras/mini-os/include/arm/arch_spinlock.h
new file mode 100755
index 0000000..6677bc4
--- /dev/null
+++ b/extras/mini-os/include/arm/arch_spinlock.h
@@ -0,0 +1,49 @@
+
+
+#ifndef __ARCH_ASM_SPINLOCK_H
+#define __ARCH_ASM_SPINLOCK_H
+
+#include "os.h"
+
+
+#define ARCH_SPIN_LOCK_UNLOCKED { 1 }
+
+/*
+ * Simple spin lock operations.  There are two variants, one clears IRQ's
+ * on the local processor, one does not.
+ *
+ * We make no fairness assumptions. They have a cost.
+ */
+
+#define arch_spin_is_locked(x) (*(volatile signed char *)(&(x)->slock) <= 0)
+#define arch_spin_unlock_wait(x) do { barrier(); } while(spin_is_locked(x))
+
+/*
+ * This works. Despite all the confusion.
+ * (except on PPro SMP or if we are using OOSTORE)
+ * (PPro errata 66, 92)
+ */
+
+static inline void _raw_spin_unlock(spinlock_t *lock)
+{
+       xchg(&lock->slock, 1);
+}
+
+static inline int _raw_spin_trylock(spinlock_t *lock)
+{
+       return xchg(&lock->slock, 0) != 0 ? 1 : 0;
+}
+
+static inline void _raw_spin_lock(spinlock_t *lock)
+{
+       volatile int was_locked;
+       do {
+               was_locked = xchg(&lock->slock, 0) == 0 ? 1 : 0;
+       } while(was_locked);
+}
+
+static inline void _raw_spin_lock_flags (spinlock_t *lock, unsigned long flags)
+{
+}
+
+#endif
diff --git a/extras/mini-os/include/arm/hypercall-arm32.h 
b/extras/mini-os/include/arm/hypercall-arm32.h
new file mode 100644
index 0000000..0343946
--- /dev/null
+++ b/extras/mini-os/include/arm/hypercall-arm32.h
@@ -0,0 +1,173 @@
+/******************************************************************************
+ * hypercall-x86_64.h
+ *
+ * Copied from XenLinux.
+ *
+ * Copyright (c) 2002-2004, K A Fraser
+ *
+ * 64-bit updates:
+ *   Benjamin Liu <benjamin.liu@xxxxxxxxx>
+ *   Jun Nakajima <jun.nakajima@xxxxxxxxx>
+ *
+ * This file may be distributed separately from the Linux kernel, or
+ * incorporated into other software packages, subject to the following license:
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this source file (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.
+ */
+
+#ifndef __HYPERCALL_ARM_H__
+#define __HYPERCALL_ARM_H__
+
+#include <xen/xen.h>
+#include <xen/sched.h>
+#include <mini-os/mm.h>
+
+inline int
+HYPERVISOR_mmu_update(
+       mmu_update_t *req, int count, int *success_count, domid_t domid);
+
+inline int
+HYPERVISOR_mmuext_op(
+       struct mmuext_op *op, int count, int *success_count, domid_t domid);
+
+inline int
+HYPERVISOR_set_gdt(
+       unsigned long *frame_list, int entries);
+
+inline int
+HYPERVISOR_stack_switch(
+       unsigned long ss, unsigned long esp);
+
+inline int
+HYPERVISOR_set_callbacks(
+       unsigned long event_address, unsigned long failsafe_address,
+       unsigned long syscall_address);
+
+inline int
+HYPERVISOR_fpu_taskswitch(
+       int set);
+
+inline int
+HYPERVISOR_sched_op(
+       int cmd, void *arg);
+
+static inline int
+HYPERVISOR_shutdown(
+       unsigned int reason)
+{
+       struct sched_shutdown shutdown = { .reason = reason };
+       return low_shutdown(&shutdown);
+}
+
+inline long
+HYPERVISOR_set_timer_op(
+       uint64_t timeout);
+
+inline int
+HYPERVISOR_set_debugreg(
+       int reg, unsigned long value);
+
+inline unsigned long
+HYPERVISOR_get_debugreg(
+       int reg);
+
+inline int
+HYPERVISOR_update_descriptor(
+       unsigned long ma, unsigned long word);
+
+inline int
+HYPERVISOR_memory_op(
+       unsigned int cmd, void *arg);
+
+inline int
+HYPERVISOR_multicall(
+       void *call_list, int nr_calls);
+
+inline int
+HYPERVISOR_update_va_mapping(
+       unsigned long va, pte_t new_val, unsigned long flags);
+
+inline int
+HYPERVISOR_event_channel_op(
+       int cmd, void *op);
+
+inline int
+HYPERVISOR_xen_version(
+       int cmd, void *arg);
+
+inline int
+HYPERVISOR_console_io(
+       int cmd, int count, char *str);
+
+inline int
+HYPERVISOR_physdev_op(
+       void *physdev_op);
+
+inline int
+HYPERVISOR_grant_table_op(
+       unsigned int cmd, void *uop, unsigned int count);
+
+inline int
+HYPERVISOR_update_va_mapping_otherdomain(
+       unsigned long va, pte_t new_val, unsigned long flags, domid_t domid);
+
+inline int
+HYPERVISOR_vm_assist(
+       unsigned int cmd, unsigned int type);
+
+inline int
+HYPERVISOR_vcpu_op(
+       int cmd, int vcpuid, void *extra_args);
+
+inline int
+HYPERVISOR_set_segment_base(
+       int reg, unsigned long value);
+
+inline int
+HYPERVISOR_suspend(
+       unsigned long srec);
+
+inline int
+HYPERVISOR_nmi_op(
+       unsigned long op,
+       unsigned long arg);
+
+inline int
+HYPERVISOR_sysctl(
+       unsigned long op);
+
+inline int
+HYPERVISOR_domctl(
+       unsigned long op);
+
+inline int
+HYPERVISOR_hvm_op(
+       unsigned long op, void *arg);
+
+#endif /* __HYPERCALL_X86_64_H__ */
+
+/*
+ * Local variables:
+ *  c-file-style: "linux"
+ *  indent-tabs-mode: t
+ *  c-indent-level: 8
+ *  c-basic-offset: 8
+ *  tab-width: 8
+ * End:
+ */
diff --git a/extras/mini-os/include/arm/os.h b/extras/mini-os/include/arm/os.h
new file mode 100644
index 0000000..60e84f7
--- /dev/null
+++ b/extras/mini-os/include/arm/os.h
@@ -0,0 +1,314 @@
+#ifndef _OS_H_
+#define _OS_H_
+
+#ifndef __ASSEMBLY__
+
+#include <mini-os/types.h>
+#include <xen/xen.h>
+
+void arch_fini(void);
+
+#define BUG() while(1){}
+
+#define smp_processor_id() 0
+
+#define barrier() __asm__ __volatile__("": : :"memory")
+
+extern shared_info_t *HYPERVISOR_shared_info;
+
+#if 0
+static inline void force_evtchn_callback(void)
+{
+    int save;
+    vcpu_info_t *vcpu;
+    vcpu = &HYPERVISOR_shared_info->vcpu_info[smp_processor_id()];
+    save = vcpu->evtchn_upcall_mask;
+
+    while (vcpu->evtchn_upcall_pending) {
+        vcpu->evtchn_upcall_mask = 1;
+        barrier();
+        do_hypervisor_callback(NULL);
+        barrier();
+        vcpu->evtchn_upcall_mask = save;
+        barrier();
+    };
+}
+#else
+#define force_evtchn_callback(void) do {} while(0)
+#endif
+
+// disable interrupts
+static inline __cli(void) {
+       int x;
+       __asm__ __volatile__("mrs %0, cpsr;cpsid i":"=r"(x)::"memory");
+}
+
+// enable interrupts
+static inline __sti(void) {
+       int x;
+       __asm__ __volatile__("mrs %0, cpsr\n"
+                                               "bic %0, %0, #0x80\n"
+                                               "msr cpsr_c, %0"
+                                               :"=r"(x)::"memory");
+}
+
+static inline int irqs_disabled() {
+       int x;
+       __asm__ __volatile__("mrs %0, cpsr\n":"=r"(x)::"memory");
+       return (x & 0x80);
+}
+
+#define local_irq_save(x) { \
+       __asm__ __volatile__("mrs %0, cpsr;cpsid i; and %0, %0, 
#0x80":"=r"(x)::"memory");        \
+}
+
+#define local_irq_restore(x) { \
+       __asm__ __volatile__("msr cpsr_c, %0"::"r"(x):"memory");  \
+}
+
+#define local_save_flags(x)    { \
+               __asm__ __volatile__("mrs %0, cpsr; and %0, %0, 
0x80":"=r"(x)::"memory"); \
+}
+
+#define local_irq_disable()    __cli()
+#define local_irq_enable() __sti()
+
+#if defined(__arm__)
+#define mb() __asm__("dmb");
+#define rmb() __asm__("dmb");
+#define wmb() __asm__("dmb");
+#elif defined(__aarch64__)
+#define mb()
+#define rmb()
+#define wmb()
+#else
+#error undefined architecture
+#endif
+
+#define LOCK_PREFIX ""
+#define LOCK ""
+
+#define unlikely(x)  __builtin_expect((x),0)
+#define likely(x)  __builtin_expect((x),1)
+
+#define ADDR (*(volatile long *) addr)
+
+/************************** arm *******************************/
+#ifdef __INSIDE_MINIOS__
+#if defined (__arm__)
+#define xchg(ptr,v) ((__typeof__(*(ptr)))__xchg((unsigned 
long)(v),(ptr),sizeof(*(ptr))))
+#define __xg(x) ((volatile long *)(x))
+
+static inline unsigned long __xchg(unsigned long x, volatile void * ptr, int 
size)
+{
+       //TODO
+       unsigned volatile long y, tmp = 0;
+       switch(size){
+       case 1:
+#if CPU_EXCLUSIVE_LDST
+               __asm__ __volatile__("1:ldrexb %0, [%1]\n"
+                       "strexb %3, %2, [%1]\n"
+                       "cmp %3, #1\n"
+                       "beq 1b\n\n"
+                       "dmb\n":"=&r"(y):"r"(ptr), "r"(x), "r"(tmp):"memory");
+#else
+               y = (*(char *)ptr) & 0x000000ff;
+               *((char *)ptr) = (char)x;
+#endif
+               break;
+       case 2:
+#if CPU_EXCLUSIVE_LDST
+               __asm__ __volatile__("1:ldrexh %0, [%1]\n"
+                       "strexh %3, %2, [%1]\n"
+                       "cmp %3, #1\n"
+                       "beq 1b\n\n"
+                       "dmb\n":"=&r"(y):"r"(ptr), "r"(x), "r"(tmp):"memory");
+#else
+               y = (*(short *)ptr) & 0x0000ffff;
+               *((short *)ptr) = (short)x;
+#endif
+               break;
+       default: // 4
+#if CPU_EXCLUSIVE_LDST
+               __asm__ __volatile__("1:ldrex %0, [%1]\n"
+                       "strex %3, %2, [%1]\n"
+                       "cmp %3, #1\n"
+                       "beq 1b\n\n"
+                       "dmb\n":"=&r"(y):"r"(ptr), "r"(x), "r"(tmp):"memory");
+#else
+               y = (*(unsigned long *)ptr) & 0xffffffff;
+               *((unsigned long *)ptr) = x;
+#endif
+               break;
+       }
+    return y;
+}
+
+/**
+ * test_and_clear_bit - Clear a bit and return its old value
+ * @nr: Bit to clear
+ * @addr: Address to count from
+ *
+ * This operation is atomic and cannot be reordered.
+ * It also implies a memory barrier.
+ */
+static __inline__ int test_and_clear_bit(int nr, volatile void * addr)
+{
+       //TODO
+       unsigned long *tmp = (unsigned long *)addr;
+
+       int x = tmp[nr >> 5] & (1 << (nr & 0x1f));
+       tmp[nr >> 5] &= ~(1 << (nr & 0x1f));
+    return x;
+}
+
+static __inline__ int test_and_set_bit(int nr, volatile void * addr)
+{
+       //TODO
+       unsigned long *tmp = (unsigned long *)addr;
+
+       int x = tmp[nr >> 5] & (1 << (nr & 0x1f));
+       tmp[nr >> 5] |= (1 << (nr & 0x1f));
+    return x;
+}
+
+static __inline__ int constant_test_bit(int nr, const volatile void * addr)
+{
+       //TODO
+       unsigned long *tmp = (unsigned long *)addr;
+    return tmp[nr >> 5] & (1 << (nr & 0x1f));
+}
+
+static __inline__ int variable_test_bit(int nr, volatile const void * addr)
+{
+       //TODO:
+       unsigned long *tmp = (unsigned long *)addr;
+       return tmp[nr >> 5] & (1 << (nr & 0x1f));
+}
+
+//TODO
+#define test_bit(nr,addr) (((unsigned long *)addr)[nr >> 5] & (1 << (nr & 
0x1f)))
+
+
+/**
+ * set_bit - Atomically set a bit in memory
+ * @nr: the bit to set
+ * @addr: the address to start counting from
+ *
+ * This function is atomic and may not be reordered.  See __set_bit()
+ * if you do not require the atomic guarantees.
+ * Note that @nr may be almost arbitrarily large; this function is not
+ * restricted to acting on a single-word quantity.
+ */
+static __inline__ void set_bit(int nr, volatile void * addr)
+{
+       //TODO:
+       unsigned long *tmp = (unsigned long *)addr;
+       tmp[nr >> 5] |= (1 << (nr & 0x1f));
+}
+
+/**
+ * clear_bit - Clears a bit in memory
+ * @nr: Bit to clear
+ * @addr: Address to start counting from
+ *
+ * clear_bit() is atomic and may not be reordered.  However, it does
+ * not contain a memory barrier, so if it is used for locking purposes,
+ * you should call smp_mb__before_clear_bit() and/or smp_mb__after_clear_bit()
+ * in order to ensure changes are visible on other processors.
+ */
+static __inline__ void clear_bit(int nr, volatile void * addr)
+{
+       //TODO
+       unsigned long *tmp = (unsigned long *)addr;
+       tmp[nr >> 5] &= (unsigned long)~(1 << (nr & 0x1f));
+}
+
+/**
+ * __ffs - find first bit in word.
+ * @word: The word to search
+ *
+ * Undefined if no bit exists, so code should check against 0 first.
+ */
+static __inline__ unsigned long __ffs(unsigned long word)
+{
+       //TODO
+       int index = 0;
+       while(!(word & (1 << index++))){};
+
+       return index - 1;
+}
+
+//FIXME
+#define rdtscll(val) (val = 0)
+
+#define wrmsr(msr,val1,val2) (0)
+
+#define wrmsrl(msr,val) 
wrmsr(msr,(uint32_t)((uint64_t)(val)),((uint64_t)(val))>>32)
+
+
+#else /* ifdef __arm__ */
+#error "Unsupported architecture"
+#endif
+#endif /* ifdef __INSIDE_MINIOS */
+
+/********************* common arm32 and arm64  ****************************/
+struct __synch_xchg_dummy { unsigned long a[100]; };
+#define __synch_xg(x) ((struct __synch_xchg_dummy *)(x))
+
+#define synch_cmpxchg(ptr, old, new) (0)
+
+static inline unsigned long __synch_cmpxchg(volatile void *ptr,
+        unsigned long old,
+        unsigned long new, int size)
+{
+       //TODO:
+    //BUG();
+    return 0;
+}
+
+
+static __inline__ void synch_set_bit(int nr, volatile void * addr)
+{
+       //TODO:
+       set_bit(nr, addr);
+}
+
+static __inline__ void synch_clear_bit(int nr, volatile void * addr)
+{
+       //TODO:
+    clear_bit(nr, addr);
+}
+
+static __inline__ int synch_test_and_set_bit(int nr, volatile void * addr)
+{
+       //TODO:
+       return test_and_set_bit(nr, addr);
+}
+
+static __inline__ int synch_test_and_clear_bit(int nr, volatile void * addr)
+{
+       //TODO:
+    return test_and_clear_bit(nr, addr);
+}
+
+static __inline__ int synch_const_test_bit(int nr, const volatile void * addr)
+{
+       //TODO:
+    return const_test_bit(nr, addr);
+}
+
+static __inline__ int synch_var_test_bit(int nr, volatile void * addr)
+{
+       //TODO:
+    return var_test_bit(nr, addr);
+}
+
+#define synch_test_bit(nr,addr) test_bit(nr, addr)
+
+
+#undef ADDR
+
+#endif /* not assembly */
+
+#endif
diff --git a/extras/mini-os/include/arm/traps.h 
b/extras/mini-os/include/arm/traps.h
new file mode 100644
index 0000000..b8ce784
--- /dev/null
+++ b/extras/mini-os/include/arm/traps.h
@@ -0,0 +1,20 @@
+#ifndef _TRAPS_H_
+#define _TRAPS_H_
+
+struct pt_regs {
+       unsigned long r0;
+       unsigned long r1;
+       unsigned long r2;
+       unsigned long r3;
+       unsigned long r4;
+       unsigned long r5;
+       unsigned long r6;
+       unsigned long r7;
+       unsigned long r8;
+       unsigned long r9;
+       unsigned long r10;
+       unsigned long r11;
+       unsigned long r12;
+};
+
+#endif
diff --git a/extras/mini-os/include/console.h b/extras/mini-os/include/console.h
index 3755b66..dade8fb 100644
--- a/extras/mini-os/include/console.h
+++ b/extras/mini-os/include/console.h
@@ -42,6 +42,7 @@
  #include <xen/grant_table.h>
  #include <xenbus.h>
  #include <xen/io/console.h>
+#include <xen/event_channel.h>
  #include <stdarg.h>

  struct consfront_dev {
diff --git a/extras/mini-os/include/hypervisor.h 
b/extras/mini-os/include/hypervisor.h
index a62cb78..ee288a0 100644
--- a/extras/mini-os/include/hypervisor.h
+++ b/extras/mini-os/include/hypervisor.h
@@ -13,16 +13,34 @@
  #define _HYPERVISOR_H_

  #include <mini-os/types.h>
+
  #include <xen/xen.h>
+
  #if defined(__i386__)
  #include <hypercall-x86_32.h>
  #elif defined(__x86_64__)
  #include <hypercall-x86_64.h>
+#elif defined(__arm__)
+#include <hypercall-arm32.h>
+#elif defined(__aarch64__)
+#include <hypercall-arm64.h>
  #else
  #error "Unsupported architecture"
  #endif
  #include <mini-os/traps.h>

+#ifdef __arm__
+struct start_info {
+    union {
+        struct {
+            xen_pfn_t mfn;
+            uint32_t  evtchn;
+        } domU;
+    } console;
+};
+typedef struct start_info start_info_t;
+#endif
+
  /*
   * a placeholder for the start of day information passed up from the 
hypervisor
   */
@@ -35,7 +53,6 @@ extern union start_info_union start_info_union;
  #define start_info (start_info_union.start_info)

  /* hypervisor.c */
-void force_evtchn_callback(void);
  void do_hypervisor_callback(struct pt_regs *regs);
  void mask_evtchn(uint32_t port);
  void unmask_evtchn(uint32_t port);
diff --git a/extras/mini-os/include/mm.h b/extras/mini-os/include/mm.h
index a94cd6d..644c7de 100644
--- a/extras/mini-os/include/mm.h
+++ b/extras/mini-os/include/mm.h
@@ -29,6 +29,8 @@
  #include <xen/arch-x86_32.h>
  #elif defined(__x86_64__)
  #include <xen/arch-x86_64.h>
+#elif defined(__arm__) || defined(__aarch64__)
+#include <xen/arch-arm.h>
  #else
  #error "Unsupported architecture"
  #endif
diff --git a/extras/mini-os/include/types.h b/extras/mini-os/include/types.h
index 6640ede..781144c 100644
--- a/extras/mini-os/include/types.h
+++ b/extras/mini-os/include/types.h
@@ -27,7 +27,7 @@ typedef unsigned char       u_char;
  typedef unsigned int        u_int;
  typedef unsigned long       u_long;
  #endif
-#ifdef __i386__
+#if defined(__i386__) || defined(__arm__)
  typedef long long           quad_t;
  typedef unsigned long long  u_quad_t;

@@ -40,7 +40,7 @@ typedef unsigned long       u_quad_t;
  typedef struct { unsigned long pte; } pte_t;
  #endif /* __i386__ || __x86_64__ */

-#ifdef __x86_64__
+#if defined(__x86_64__) || defined(__aarch64__)
  #define __pte(x) ((pte_t) { (x) } )
  #else
  #define __pte(x) ({ unsigned long long _x = (x);        \
@@ -51,10 +51,10 @@ typedef struct { unsigned long pte; } pte_t;
  #include <limits.h>
  #include <stdint.h>
  #else
-#ifdef __i386__
+#if defined(__i386__) || defined(__arm__)
  typedef unsigned int        uintptr_t;
  typedef int                 intptr_t;
-#elif defined(__x86_64__)
+#elif defined(__x86_64__) || defined(__aarch64__)
  typedef unsigned long       uintptr_t;
  typedef long                intptr_t;
  #endif /* __i386__ || __x86_64__ */
@@ -64,10 +64,10 @@ typedef unsigned short uint16_t;
  typedef   signed short int16_t;
  typedef unsigned int uint32_t;
  typedef   signed int int32_t;
-#ifdef __i386__
+#if defined(__i386__) || defined(__arm__)
  typedef   signed long long int64_t;
  typedef unsigned long long uint64_t;
-#elif defined(__x86_64__)
+#elif defined(__x86_64__) || defined(__aarch64__)
  typedef   signed long int64_t;
  typedef unsigned long uint64_t;
  #endif
@@ -83,4 +83,65 @@ typedef intptr_t            ptrdiff_t;
  typedef long ssize_t;
  #endif

+#ifdef __arm__
+/*
+ * From
+ *     @(#)quad.h      8.1 (Berkeley) 6/4/93
+ */
+
+#ifdef __BIG_ENDIAN
+#define _QUAD_HIGHWORD 0
+#define _QUAD_LOWWORD 1
+#else /* __LITTLE_ENDIAN */
+#define _QUAD_HIGHWORD 1
+#define _QUAD_LOWWORD 0
+#endif
+
+/*
+ * Define high and low longwords.
+ */
+#define H               _QUAD_HIGHWORD
+#define L               _QUAD_LOWWORD
+
+/*
+ * Total number of bits in a quad_t and in the pieces that make it up.
+ * These are used for shifting, and also below for halfword extraction
+ * and assembly.
+ */
+#define CHAR_BIT        8               /* number of bits in a char */
+#define QUAD_BITS       (sizeof(s64) * CHAR_BIT)
+#define LONG_BITS       (sizeof(long) * CHAR_BIT)
+#define HALF_BITS       (sizeof(long) * CHAR_BIT / 2)
+
+#define B (1 << HALF_BITS) /* digit base */
+/*
+ * Extract high and low shortwords from longword, and move low shortword of
+ * longword to upper half of long, i.e., produce the upper longword of
+ * ((quad_t)(x) << (number_of_bits_in_long/2)).  (`x' must actually be u_long.)
+ *
+ * These are used in the multiply code, to split a longword into upper
+ * and lower halves, and to reassemble a product as a quad_t, shifted left
+ * (sizeof(long)*CHAR_BIT/2).
+ */
+#define HHALF(x)        ((x) >> HALF_BITS)
+#define LHALF(x)        ((x) & ((1 << HALF_BITS) - 1))
+#define LHUP(x)         ((x) << HALF_BITS)
+
+#define COMBINE(a, b) (((u_long)(a) << HALF_BITS) | (b))
+
+/*
+ * Depending on the desired operation, we view a `long long' (aka quad_t) in
+ * one or more of the following formats.
+ */
+union uu {
+    int64_t            q;              /* as a (signed) quad */
+    int64_t            uq;             /* as an unsigned quad */
+    long           sl[2];          /* as two signed longs */
+    unsigned long  ul[2];          /* as two unsigned longs */
+};
+
+/* select a type for digits in base B */
+typedef u_long digit;
+#endif
+
  #endif /* _TYPES_H_ */
diff --git a/extras/mini-os/include/x86/arch_mm.h 
b/extras/mini-os/include/x86/arch_mm.h
index 23cfca7..3b74cd7 100644
--- a/extras/mini-os/include/x86/arch_mm.h
+++ b/extras/mini-os/include/x86/arch_mm.h
@@ -25,6 +25,8 @@
  #ifndef _ARCH_MM_H_
  #define _ARCH_MM_H_

+extern char stack[];
+
  #ifndef __ASSEMBLY__
  #include <xen/xen.h>
  #if defined(__i386__)
diff --git a/extras/mini-os/include/x86/os.h b/extras/mini-os/include/x86/os.h
index f193865..8eea1be 100644
--- a/extras/mini-os/include/x86/os.h
+++ b/extras/mini-os/include/x86/os.h
@@ -64,8 +64,6 @@ extern shared_info_t *HYPERVISOR_shared_info;
  void trap_init(void);
  void trap_fini(void);

-void arch_init(start_info_t *si);
-void arch_print_info(void);
  void arch_fini(void);


@@ -162,6 +160,23 @@ do {                                                       
                \
   */
  typedef struct { volatile int counter; } atomic_t;

+static inline void force_evtchn_callback(void)
+{
+    int save;
+    vcpu_info_t *vcpu;
+    vcpu = &HYPERVISOR_shared_info->vcpu_info[smp_processor_id()];
+    save = vcpu->evtchn_upcall_mask;
+
+    while (vcpu->evtchn_upcall_pending) {
+        vcpu->evtchn_upcall_mask = 1;
+        barrier();
+        do_hypervisor_callback(NULL);
+        barrier();
+        vcpu->evtchn_upcall_mask = save;
+        barrier();
+    };
+}
+

  /************************** i386 *******************************/
  #ifdef __INSIDE_MINIOS__
diff --git a/extras/mini-os/include/x86/x86_64/hypercall-x86_64.h 
b/extras/mini-os/include/x86/x86_64/hypercall-x86_64.h
index 7083763..4581574 100644
--- a/extras/mini-os/include/x86/x86_64/hypercall-x86_64.h
+++ b/extras/mini-os/include/x86/x86_64/hypercall-x86_64.h
@@ -37,6 +37,7 @@
  #include <xen/xen.h>
  #include <xen/sched.h>
  #include <mini-os/mm.h>
+#include <arch_mm.h>

  #define __STR(x) #x
  #define STR(x) __STR(x)
diff --git a/extras/mini-os/kernel.c b/extras/mini-os/kernel.c
index 386be8f..de25921 100644
--- a/extras/mini-os/kernel.c
+++ b/extras/mini-os/kernel.c
@@ -27,7 +27,6 @@
   * DEALINGS IN THE SOFTWARE.
   */

-#include <mini-os/os.h>
  #include <mini-os/hypervisor.h>
  #include <mini-os/mm.h>
  #include <mini-os/events.h>
@@ -118,40 +117,14 @@ __attribute__((weak)) int app_main(start_info_t *si)
      return 0;
  }

-/*
- * INITIAL C ENTRY POINT.
- */
-void start_kernel(start_info_t *si)
-{
-    static char hello[] = "Bootstrapping...\n";
-
-    (void)HYPERVISOR_console_io(CONSOLEIO_write, strlen(hello), hello);
-
-    arch_init(si);
-
-    trap_init();
-
-    /* print out some useful information  */
-    printk("Xen Minimal OS!\n");
-    printk("  start_info: %p(VA)\n", si);
-    printk("    nr_pages: 0x%lx\n", si->nr_pages);
-    printk("  shared_inf: 0x%08lx(MA)\n", si->shared_info);
-    printk("     pt_base: %p(VA)\n", (void *)si->pt_base);
-    printk("nr_pt_frames: 0x%lx\n", si->nr_pt_frames);
-    printk("    mfn_list: %p(VA)\n", (void *)si->mfn_list);
-    printk("   mod_start: 0x%lx(VA)\n", si->mod_start);
-    printk("     mod_len: %lu\n", si->mod_len);
-    printk("       flags: 0x%x\n", (unsigned int)si->flags);
-    printk("    cmd_line: %s\n",
-           si->cmd_line ? (const char *)si->cmd_line : "NULL");
+void gic_init(void);

+void start_kernel(void)
+{
      /* Set up events. */
      init_events();
-
-    /* ENABLE EVENT DELIVERY. This is disabled at start of day. */
-    __sti();

-    arch_print_info();
+    __sti();

      setup_xen_features();

@@ -161,24 +134,58 @@ void start_kernel(start_info_t *si)
      /* Init time and timers. */
      init_time();

+#ifndef __arm__
      /* Init the console driver. */
      init_console();
+#endif

      /* Init grant tables */
      init_gnttab();
-
+
      /* Init scheduler. */
      init_sched();

      /* Init XenBus */
      init_xenbus();

+
  #ifdef CONFIG_XENBUS
      create_thread("shutdown", shutdown_thread, NULL);
  #endif

+#ifdef __arm__
+    gic_init();
+#endif
+
+//#define VTIMER_TEST
+#ifdef VTIMER_TEST
+    while(1){
+               int x, y, z;
+       z = 0;
+       // counter
+       __asm__ __volatile__("mrrc p15, 1, %0, %1, c14;isb":"=r"(x), "=r"(y));
+       printk("Counter: %x-%x\n", x, y);
+
+       __asm__ __volatile__("mrrc p15, 3, %0, %1, c14;isb":"=r"(x), "=r"(y));
+       printk("CompareValue: %x-%x\n", x, y);
+
+       // TimerValue
+       __asm__ __volatile__("mrc p15, 0, %0, c14, c3, 0;isb":"=r"(x));
+       printk("TimerValue: %x\n", x);
+
+       // control register
+       __asm__ __volatile__("mrc p15, 0, %0, c14, c3, 1;isb":"=r"(x));
+       printk("ControlRegister: %x\n", x);
+       while(z++ < 0xfffff){}
+    }
+#endif
+
      /* Call (possibly overridden) app_main() */
+#if defined(__arm__) || defined(__aarch64__)
+    app_main(NULL);
+#else
      app_main(&start_info);
+#endif

      /* Everything initialised, start idle thread */
      run_idle_thread();
@@ -205,13 +212,12 @@ void stop_kernel(void)
      /* Reset events. */
      fini_events();

-    /* Reset traps */
-    trap_fini();
-
      /* Reset arch details */
      arch_fini();
  }

+void arch_do_exit(void);
+
  /*
   * do_exit: This is called whenever an IRET fails in entry.S.
   * This will generally be because an application has got itself into
@@ -222,7 +228,7 @@ void stop_kernel(void)
  void do_exit(void)
  {
      printk("Do_exit called!\n");
-    stack_walk();
+    arch_do_exit();
      for( ;; )
      {
          struct sched_shutdown sched_shutdown = { .reason = SHUTDOWN_crash };
diff --git a/extras/mini-os/mm.c b/extras/mini-os/mm.c
index d2d5264..ab76018 100644
--- a/extras/mini-os/mm.c
+++ b/extras/mini-os/mm.c
@@ -213,22 +213,26 @@ static void init_page_allocator(unsigned long min, 
unsigned long max)
      min = round_pgup  (min);
      max = round_pgdown(max);

+
      /* Allocate space for the allocation bitmap. */
-    bitmap_size  = (max+1) >> (PAGE_SHIFT+3);
+    bitmap_size  = (max - min + 1) >> (PAGE_SHIFT+3);
      bitmap_size  = round_pgup(bitmap_size);
      alloc_bitmap = (unsigned long *)to_virt(min);
      min         += bitmap_size;
      range        = max - min;

+
      /* All allocated by default. */
      memset(alloc_bitmap, ~0, bitmap_size);
      /* Free up the memory we've been given to play with. */
      map_free(PHYS_PFN(min), range>>PAGE_SHIFT);

+
      /* The buddy lists are addressed in high memory. */
      min = (unsigned long) to_virt(min);
      max = (unsigned long) to_virt(max);

+
      while ( range != 0 )
      {
          /*
@@ -238,7 +242,6 @@ static void init_page_allocator(unsigned long min, unsigned 
long max)
          for ( i = PAGE_SHIFT; (1UL<<(i+1)) <= range; i++ )
              if ( min & (1UL<<i) ) break;

-
          ch = (chunk_head_t *)min;
          min   += (1UL<<i);
          range -= (1UL<<i);
@@ -399,9 +402,7 @@ void *sbrk(ptrdiff_t increment)

  void init_mm(void)
  {
-
      unsigned long start_pfn, max_pfn;
-
      printk("MM: Init\n");

      arch_init_mm(&start_pfn, &max_pfn);
diff --git a/extras/mini-os/sched.c b/extras/mini-os/sched.c
index 174945e..a1cd3a9 100644
--- a/extras/mini-os/sched.c
+++ b/extras/mini-os/sched.c
@@ -100,15 +100,19 @@ void schedule(void)
          next = NULL;
          MINIOS_TAILQ_FOREACH_SAFE(thread, &thread_list, thread_list, tmp)
          {
+               DEBUG("Checking thread : %s (runnable:%i)\n", thread->name, 
is_runnable(thread));
              if (!is_runnable(thread) && thread->wakeup_time != 0LL)
              {
-                if (thread->wakeup_time <= now)
+                if (thread->wakeup_time <= now) {
+                       DEBUG("Wake thread : %s\n", thread->name);
                      wake(thread);
+                }
                  else if (thread->wakeup_time < min_wakeup_time)
                      min_wakeup_time = thread->wakeup_time;
              }
              if(is_runnable(thread))
              {
+               DEBUG("Thread (%s) is runnable, put it next\n", thread->name);
                  next = thread;
                  /* Put this thread on the end of the list */
                  MINIOS_TAILQ_REMOVE(&thread_list, thread, thread_list);
@@ -145,6 +149,9 @@ struct thread* create_thread(char *name, void 
(*function)(void *), void *data)
      unsigned long flags;
      /* Call architecture specific setup. */
      thread = arch_create_thread(name, function, data);
+    if(!thread)
+       BUG(); //For now, FIXME should just return NULL
+
      /* Not runable, not exited, not sleeping */
      thread->flags = 0;
      thread->wakeup_time = 0LL;
diff --git a/extras/mini-os/time.c b/extras/mini-os/time.c
new file mode 100644
index 0000000..4320241
--- /dev/null
+++ b/extras/mini-os/time.c
@@ -0,0 +1,12 @@
+void arch_init_time(void);
+void arch_fini_time(void);
+
+void init_time(void)
+{
+       arch_init_time();
+}
+
+void fini_time(void)
+{
+       arch_fini_time();
+}
diff --git a/extras/mini-os/xenbus/xenbus.c b/extras/mini-os/xenbus/xenbus.c
index 934f23b..8a99ee2 100644
--- a/extras/mini-os/xenbus/xenbus.c
+++ b/extras/mini-os/xenbus/xenbus.c
@@ -27,6 +27,7 @@
  #include <mini-os/wait.h>
  #include <xen/io/xs_wire.h>
  #include <mini-os/spinlock.h>
+#include <mini-os/hypervisor.h>
  #include <mini-os/xmalloc.h>

  #define min(x,y) ({                       \
@@ -43,6 +44,7 @@
  #endif

  static struct xenstore_domain_interface *xenstore_buf;
+static uint32_t store_evtchn;
  static DECLARE_WAIT_QUEUE_HEAD(xb_waitq);
  DECLARE_WAIT_QUEUE_HEAD(xenbus_watch_queue);

@@ -325,20 +327,23 @@ static int allocate_xenbus_id(void)
      return o_probe;
  }

+void arch_init_xenbus(struct xenstore_domain_interface **xenstore_buf, 
uint32_t *store_evtchn);
+
  /* Initialise xenbus. */
  void init_xenbus(void)
  {
      int err;
      DEBUG("init_xenbus called.\n");
-    xenstore_buf = mfn_to_virt(start_info.store_mfn);
+
+    arch_init_xenbus(&xenstore_buf, &store_evtchn);
+
      create_thread("xenstore", xenbus_thread_func, NULL);
      DEBUG("buf at %p.\n", xenstore_buf);
-    err = bind_evtchn(start_info.store_evtchn,
+    err = bind_evtchn(store_evtchn,
                      xenbus_evtchn_handler,
                NULL);
-    unmask_evtchn(start_info.store_evtchn);
-    printk("xenbus initialised on irq %d mfn %#lx\n",
-          err, start_info.store_mfn);
+    unmask_evtchn(store_evtchn);
+    printk("xenbus initialised on event %d\n", err);
  }

  void fini_xenbus(void)
@@ -420,7 +425,7 @@ static void xb_write(int type, int req_id, 
xenbus_transaction_t trans_id,
      xenstore_buf->req_prod += len;

      /* Send evtchn to notify remote */
-    notify_remote_via_evtchn(start_info.store_evtchn);
+    notify_remote_via_evtchn(store_evtchn);
  }

  /* Send a mesasge to xenbus, in the same fashion as xb_write, and
@@ -445,6 +450,7 @@ xenbus_msg_reply(int type,
      remove_waiter(w, req_info[id].waitq);
      wake(current);

+    rmb();
      rep = req_info[id].reply;
      BUG_ON(rep->req_id != id);
      release_xenbus_id(id);


--
Julien Grall

_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.