From mboxrd@z Thu Jan 1 00:00:00 1970 From: Julien Grall Subject: Re: [PATCH 3/4] mini-os: Initial commit to port minios to ARM Date: Tue, 03 Jun 2014 10:12:01 +0100 Message-ID: <538D9161.6090402@linaro.org> References: <1401731397-29842-1-git-send-email-talex5@gmail.com> <1401731397-29842-4-git-send-email-talex5@gmail.com> Mime-Version: 1.0 Content-Type: text/plain; charset="us-ascii"; Format="flowed" Content-Transfer-Encoding: 7bit Return-path: Received: from mail6.bemta5.messagelabs.com ([195.245.231.135]) by lists.xen.org with esmtp (Exim 4.72) (envelope-from ) id 1WrklU-0001fg-Dy for xen-devel@lists.xenproject.org; Tue, 03 Jun 2014 09:12:17 +0000 Received: by mail-lb0-f177.google.com with SMTP id s7so3165021lbd.8 for ; Tue, 03 Jun 2014 02:12:04 -0700 (PDT) In-Reply-To: <1401731397-29842-4-git-send-email-talex5@gmail.com> List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Sender: xen-devel-bounces@lists.xen.org Errors-To: xen-devel-bounces@lists.xen.org To: Thomas Leonard , xen-devel@lists.xenproject.org Cc: samuel.thibault@ens-lyon.org, stefano.stabellini@eu.citrix.com List-Id: xen-devel@lists.xenproject.org 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 > > 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 > [talex5@gmail.com: made x86_64 support work again] > [talex5@gmail.com: split into multiple patches] > Signed-off-by: Thomas Leonard > --- > 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, , c1, c0, 1 > + mcr p15, 0, , 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 > +#include > +#include > + > +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 > + > +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 > +#include > + > +#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 > + > +/* > + * 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 > +#include > + > + > +/* 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 > +#include > +#include > +#include > +#include > + > +/* > + * 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 > +#include > +#include > +#include > +#include > +#include > +#include > + > +//#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 > +#include > +#include > +#include > +#include > + > +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 > +#include > + > +#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 > #include /* for printk, memcpy */ > +#include > > /* > * 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 > +#include > +#include > +#include > +#include > + > +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 > +#include > + > +//#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 > #include > #include > +#include > > //#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 > #include > #include > +#include > > #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 > + > +#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 > + * Jun Nakajima > + * > + * 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 > +#include > +#include > + > +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 > +#include > + > +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 > #include > #include > +#include > #include > > 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 > + > #include > + > #if defined(__i386__) > #include > #elif defined(__x86_64__) > #include > +#elif defined(__arm__) > +#include > +#elif defined(__aarch64__) > +#include > #else > #error "Unsupported architecture" > #endif > #include > > +#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 > #elif defined(__x86_64__) > #include > +#elif defined(__arm__) || defined(__aarch64__) > +#include > #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 > #include > #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 > #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 > #include > #include > +#include > > #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 > #include > #include > #include > @@ -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< > - > ch = (chunk_head_t *)min; > min += (1UL< range -= (1UL< @@ -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 > #include > #include > +#include > #include > > #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