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
next prev parent reply other threads:[~2014-06-03 9:12 UTC|newest]
Thread overview: 44+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-06-02 17:49 [PATCH 0/4] mini-os: initial ARM support Thomas Leonard
2014-06-02 17:49 ` [PATCH 1/4] mini-os: Fixed shutdown thread Thomas Leonard
2014-06-03 0:51 ` Samuel Thibault
2014-06-03 9:01 ` Andrew Cooper
2014-06-02 17:49 ` [PATCH 2/4] mini-os: Tidied up code Thomas Leonard
2014-06-03 0:57 ` Samuel Thibault
2014-06-02 17:49 ` [PATCH 3/4] mini-os: Initial commit to port minios to ARM Thomas Leonard
2014-06-03 9:12 ` Julien Grall [this message]
2014-06-04 16:06 ` [PATCH 0/7] mini-os: Preparing for ARM support Thomas Leonard
2014-06-04 16:06 ` [PATCH 1/7] mini-os: Fixed shutdown thread Thomas Leonard
2014-06-04 16:06 ` [PATCH 2/7] mini-os: Tidied up code Thomas Leonard
2014-06-04 16:22 ` Andrew Cooper
2014-06-05 10:24 ` Anil Madhavapeddy
2014-06-04 16:06 ` [PATCH 3/7] mini-os: Moved events code under arch Thomas Leonard
2014-06-04 16:23 ` Julien Grall
2014-06-06 13:54 ` Ian Campbell
2014-06-06 13:57 ` Ian Campbell
2014-06-04 16:06 ` [PATCH 4/7] mini-os: Switched initial C entry point to arch_init Thomas Leonard
2014-06-06 14:05 ` Ian Campbell
2014-06-04 16:06 ` [PATCH 5/7] mini-os: Moved arch-specific xenbus code under arch Thomas Leonard
2014-06-05 14:00 ` Julien Grall
2014-06-06 14:07 ` Ian Campbell
2014-06-04 16:06 ` [PATCH 6/7] mini-os: Added rmb to xenbus code Thomas Leonard
2014-06-05 13:55 ` Julien Grall
2014-06-05 17:45 ` Thomas Leonard
2014-06-06 4:59 ` karim.allah.ahmed
2014-06-06 14:15 ` Ian Campbell
2014-06-06 15:10 ` Samuel Thibault
2014-06-06 16:40 ` Ian Campbell
2014-06-09 13:56 ` Thomas Leonard
2014-06-09 14:04 ` Thomas Leonard
2014-06-04 16:06 ` [PATCH 7/7] mini-os: Moved force_evtchn_callback to header Thomas Leonard
2014-06-06 14:17 ` Ian Campbell
2014-06-09 11:54 ` Thomas Leonard
2014-06-04 16:12 ` [PATCH 0/7] mini-os: Preparing for ARM support Andrew Cooper
2014-06-02 17:49 ` [PATCH 4/4] mini-os: Added FDT support on ARM Thomas Leonard
2014-06-06 13:51 ` Ian Campbell
2014-06-05 14:36 ` [PATCH 0/4] mini-os: initial ARM support Oleksandr Tyshchenko
2014-06-05 14:57 ` Samuel Thibault
2014-06-05 17:20 ` Oleksandr Tyshchenko
2014-06-05 17:31 ` Thomas Leonard
2014-06-05 18:07 ` Oleksandr Tyshchenko
2014-06-05 18:12 ` Thomas Leonard
2014-06-05 18:21 ` Oleksandr Tyshchenko
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=538D9161.6090402@linaro.org \
--to=julien.grall@linaro.org \
--cc=samuel.thibault@ens-lyon.org \
--cc=stefano.stabellini@eu.citrix.com \
--cc=talex5@gmail.com \
--cc=xen-devel@lists.xenproject.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).