All of lore.kernel.org
 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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.