xen-devel.lists.xenproject.org archive mirror
 help / color / mirror / Atom feed
From: Julien Grall <julien.grall@linaro.org>
To: Thomas Leonard <talex5@gmail.com>, xen-devel@lists.xenproject.org
Cc: samuel.thibault@ens-lyon.org, stefano.stabellini@eu.citrix.com
Subject: Re: [PATCH 3/4] mini-os: Initial commit to port minios to ARM
Date: Tue, 03 Jun 2014 10:12:01 +0100	[thread overview]
Message-ID: <538D9161.6090402@linaro.org> (raw)
In-Reply-To: <1401731397-29842-4-git-send-email-talex5@gmail.com>

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@gmail.com>
>
> 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@gmail.com>
> [talex5@gmail.com: made x86_64 support work again]
> [talex5@gmail.com: split into multiple patches]
> Signed-off-by: Thomas Leonard <talex5@gmail.com>
> ---
>   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@intel.com>
> + *   Jun Nakajima <jun.nakajima@intel.com>
> + *
> + * 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

  reply	other threads:[~2014-06-03  9:12 UTC|newest]

Thread overview: 44+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-06-02 17:49 [PATCH 0/4] mini-os: initial ARM support Thomas Leonard
2014-06-02 17:49 ` [PATCH 1/4] mini-os: Fixed shutdown thread Thomas Leonard
2014-06-03  0:51   ` Samuel Thibault
2014-06-03  9:01   ` Andrew Cooper
2014-06-02 17:49 ` [PATCH 2/4] mini-os: Tidied up code Thomas Leonard
2014-06-03  0:57   ` Samuel Thibault
2014-06-02 17:49 ` [PATCH 3/4] mini-os: Initial commit to port minios to ARM Thomas Leonard
2014-06-03  9:12   ` Julien Grall [this message]
2014-06-04 16:06     ` [PATCH 0/7] mini-os: Preparing for ARM support Thomas Leonard
2014-06-04 16:06       ` [PATCH 1/7] mini-os: Fixed shutdown thread Thomas Leonard
2014-06-04 16:06       ` [PATCH 2/7] mini-os: Tidied up code Thomas Leonard
2014-06-04 16:22         ` Andrew Cooper
2014-06-05 10:24           ` Anil Madhavapeddy
2014-06-04 16:06       ` [PATCH 3/7] mini-os: Moved events code under arch Thomas Leonard
2014-06-04 16:23         ` Julien Grall
2014-06-06 13:54           ` Ian Campbell
2014-06-06 13:57         ` Ian Campbell
2014-06-04 16:06       ` [PATCH 4/7] mini-os: Switched initial C entry point to arch_init Thomas Leonard
2014-06-06 14:05         ` Ian Campbell
2014-06-04 16:06       ` [PATCH 5/7] mini-os: Moved arch-specific xenbus code under arch Thomas Leonard
2014-06-05 14:00         ` Julien Grall
2014-06-06 14:07         ` Ian Campbell
2014-06-04 16:06       ` [PATCH 6/7] mini-os: Added rmb to xenbus code Thomas Leonard
2014-06-05 13:55         ` Julien Grall
2014-06-05 17:45           ` Thomas Leonard
2014-06-06  4:59             ` karim.allah.ahmed
2014-06-06 14:15               ` Ian Campbell
2014-06-06 15:10                 ` Samuel Thibault
2014-06-06 16:40                   ` Ian Campbell
2014-06-09 13:56                     ` Thomas Leonard
2014-06-09 14:04                       ` Thomas Leonard
2014-06-04 16:06       ` [PATCH 7/7] mini-os: Moved force_evtchn_callback to header Thomas Leonard
2014-06-06 14:17         ` Ian Campbell
2014-06-09 11:54           ` Thomas Leonard
2014-06-04 16:12       ` [PATCH 0/7] mini-os: Preparing for ARM support Andrew Cooper
2014-06-02 17:49 ` [PATCH 4/4] mini-os: Added FDT support on ARM Thomas Leonard
2014-06-06 13:51   ` Ian Campbell
2014-06-05 14:36 ` [PATCH 0/4] mini-os: initial ARM support Oleksandr Tyshchenko
2014-06-05 14:57   ` Samuel Thibault
2014-06-05 17:20     ` Oleksandr Tyshchenko
2014-06-05 17:31   ` Thomas Leonard
2014-06-05 18:07     ` Oleksandr Tyshchenko
2014-06-05 18:12       ` Thomas Leonard
2014-06-05 18:21         ` Oleksandr Tyshchenko

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=538D9161.6090402@linaro.org \
    --to=julien.grall@linaro.org \
    --cc=samuel.thibault@ens-lyon.org \
    --cc=stefano.stabellini@eu.citrix.com \
    --cc=talex5@gmail.com \
    --cc=xen-devel@lists.xenproject.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).