[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] [PATCH 3/4] mini-os: Initial commit to port minios to ARM
Hi Thomas, Thank you for the port of Minos on ARM! This patch is a bit complex to read (nearly 3000 lines).There is some change in the common code. It might be easier to move all those changes in a separate patch. Same for the code imported from NetBSD. Regards, On 02/06/14 18:49, Thomas Leonard wrote: From: Karim Raslan <karim.allah.ahmed@xxxxxxxxx> On ARM, Mini-OS will boot and display some output on the Xen emergency console (only visible if Xen is compiled in debug mode). Tested with: make XEN_TARGET_ARCH=arm32 CROSS_COMPILE=arm-linux-gnueabihf- \ CONFIG_TEST=n CONFIG_START_NETWORK=n CONFIG_BLKFRONT=n \ CONFIG_NETFRONT=n CONFIG_FBFRONT=n CONFIG_KBDFRONT=n \ CONFIG_CONSFRONT=n CONFIG_XC=n Signed-off-by: Karim Allah Ahmed <karim.allah.ahmed@xxxxxxxxx> [talex5@xxxxxxxxx: made x86_64 support work again] [talex5@xxxxxxxxx: split into multiple patches] Signed-off-by: Thomas Leonard <talex5@xxxxxxxxx> --- extras/mini-os/ARM-TODO.txt | 19 + extras/mini-os/Config.mk | 2 + extras/mini-os/Makefile | 12 + extras/mini-os/arch/arm/Makefile | 33 ++ extras/mini-os/arch/arm/arch.mk | 6 + extras/mini-os/arch/arm/arm32.S | 211 +++++++++++ extras/mini-os/arch/arm/divsi3.S | 404 +++++++++++++++++++++ extras/mini-os/arch/arm/events.c | 24 ++ extras/mini-os/arch/arm/hypercalls32.S | 88 +++++ extras/mini-os/arch/arm/ldivmod.S | 67 ++++ extras/mini-os/arch/arm/ldivmod_helper.c | 66 ++++ extras/mini-os/arch/arm/minios-arm32.lds | 73 ++++ extras/mini-os/arch/arm/mm.c | 44 +++ extras/mini-os/arch/arm/qdivrem.c | 270 ++++++++++++++ extras/mini-os/arch/arm/sched.c | 32 ++ extras/mini-os/arch/arm/setup.c | 55 +++ extras/mini-os/arch/arm/time.c | 232 ++++++++++++ extras/mini-os/arch/arm/xenbus.c | 36 ++ extras/mini-os/arch/x86/events.c | 28 ++ extras/mini-os/arch/x86/setup.c | 44 ++- extras/mini-os/arch/x86/time.c | 4 +- extras/mini-os/arch/x86/x86_32.S | 2 +- extras/mini-os/arch/x86/x86_64.S | 2 +- extras/mini-os/arch/x86/xenbus.c | 10 + extras/mini-os/console/console.c | 2 + extras/mini-os/drivers/gic.c | 179 +++++++++ extras/mini-os/events.c | 32 +- extras/mini-os/gntmap.c | 1 + extras/mini-os/gnttab.c | 1 + extras/mini-os/hypervisor.c | 20 +- extras/mini-os/include/arm/arch_limits.h | 9 + extras/mini-os/include/arm/arch_mm.h | 37 ++ extras/mini-os/include/arm/arch_sched.h | 22 ++ extras/mini-os/include/arm/arch_spinlock.h | 49 +++ extras/mini-os/include/arm/hypercall-arm32.h | 173 +++++++++ extras/mini-os/include/arm/os.h | 314 ++++++++++++++++ extras/mini-os/include/arm/traps.h | 20 + extras/mini-os/include/console.h | 1 + extras/mini-os/include/hypervisor.h | 19 +- extras/mini-os/include/mm.h | 2 + extras/mini-os/include/types.h | 73 +++- extras/mini-os/include/x86/arch_mm.h | 2 + extras/mini-os/include/x86/os.h | 19 +- .../mini-os/include/x86/x86_64/hypercall-x86_64.h | 1 + extras/mini-os/kernel.c | 78 ++-- extras/mini-os/mm.c | 9 +- extras/mini-os/sched.c | 9 +- extras/mini-os/time.c | 12 + extras/mini-os/xenbus/xenbus.c | 18 +- 49 files changed, 2758 insertions(+), 108 deletions(-) create mode 100644 extras/mini-os/ARM-TODO.txt create mode 100755 extras/mini-os/arch/arm/Makefile create mode 100644 extras/mini-os/arch/arm/arch.mk create mode 100644 extras/mini-os/arch/arm/arm32.S create mode 100644 extras/mini-os/arch/arm/divsi3.S create mode 100644 extras/mini-os/arch/arm/events.c create mode 100644 extras/mini-os/arch/arm/hypercalls32.S create mode 100644 extras/mini-os/arch/arm/ldivmod.S create mode 100644 extras/mini-os/arch/arm/ldivmod_helper.c create mode 100755 extras/mini-os/arch/arm/minios-arm32.lds create mode 100644 extras/mini-os/arch/arm/mm.c create mode 100644 extras/mini-os/arch/arm/qdivrem.c create mode 100644 extras/mini-os/arch/arm/sched.c create mode 100644 extras/mini-os/arch/arm/setup.c create mode 100644 extras/mini-os/arch/arm/time.c create mode 100644 extras/mini-os/arch/arm/xenbus.c create mode 100644 extras/mini-os/arch/x86/events.c create mode 100644 extras/mini-os/arch/x86/xenbus.c create mode 100644 extras/mini-os/drivers/gic.c create mode 100644 extras/mini-os/include/arm/arch_limits.h create mode 100644 extras/mini-os/include/arm/arch_mm.h create mode 100644 extras/mini-os/include/arm/arch_sched.h create mode 100755 extras/mini-os/include/arm/arch_spinlock.h create mode 100644 extras/mini-os/include/arm/hypercall-arm32.h create mode 100644 extras/mini-os/include/arm/os.h create mode 100644 extras/mini-os/include/arm/traps.h create mode 100644 extras/mini-os/time.c diff --git a/extras/mini-os/ARM-TODO.txt b/extras/mini-os/ARM-TODO.txt new file mode 100644 index 0000000..57d531a --- /dev/null +++ b/extras/mini-os/ARM-TODO.txt @@ -0,0 +1,19 @@ +* os.h bit manipulation, write optimized assembly code +* support abort exception handling ( and others ) +* scheduling! +* use proper memory types and enable caches (L1 and L2) +* Use LDREX and STREX in xchg implementation ( code already there but it causes an abort, I think because of using strong-ordered memory with disabled L1 caches - something to do with the implementation of the monitor on cortex-a7 ) +* gic request_irq implementation, currently all IRQs all hardcoded in gic irq handler. +* use device tree instead of the currently hardcoded values +* Add virtual memory support and make vstart = 0 ( use 4k descriptors instead of 1M descriptors ) +* sched +* fini_gnttab +* fini_time +* bind_* +* add multiple cpu support (?) +* map_frames +* clean up the code and remove redundent code between arm and x86 +* remove start_info structure from the common code +* make sure that wallclock is functioning properly +* console support +* evtchn_get_peercontext diff --git a/extras/mini-os/Config.mk b/extras/mini-os/Config.mk index d61877b..4ecde54 100644 --- a/extras/mini-os/Config.mk +++ b/extras/mini-os/Config.mk @@ -12,6 +12,8 @@ export XEN_INTERFACE_VERSION # If not x86 then use $(XEN_TARGET_ARCH) ifeq ($(findstring x86_,$(XEN_TARGET_ARCH)),x86_) TARGET_ARCH_FAM = x86 +else ifeq ($(findstring arm,$(XEN_TARGET_ARCH)),arm) +TARGET_ARCH_FAM = arm else TARGET_ARCH_FAM = $(XEN_TARGET_ARCH) endif diff --git a/extras/mini-os/Makefile b/extras/mini-os/Makefile index 50d038b..0fd38a8 100644 --- a/extras/mini-os/Makefile +++ b/extras/mini-os/Makefile @@ -72,6 +72,11 @@ TARGET := mini-os # Subdirectories common to mini-os SUBDIRS := lib xenbus console +ifeq ($(XEN_TARGET_ARCH),arm32) +# ARM drivers +src-y += drivers/gic.c +endif + src-$(CONFIG_BLKFRONT) += blkfront.c src-$(CONFIG_TPMFRONT) += tpmfront.c src-$(CONFIG_TPM_TIS) += tpm_tis.c @@ -82,6 +87,7 @@ src-$(CONFIG_FBFRONT) += fbfront.c src-y += gntmap.c src-y += gnttab.c src-y += hypervisor.c +src-y += time.c src-y += kernel.c src-y += lock.c src-y += main.c @@ -92,7 +98,9 @@ src-y += sched.c src-$(CONFIG_TEST) += test.c src-y += lib/ctype.c +ifneq ($(XEN_TARGET_ARCH),arm32) src-y += lib/math.c +endif src-y += lib/printf.c src-y += lib/stack_chk_fail.c src-y += lib/string.c @@ -178,7 +186,11 @@ $(OBJ_DIR)/$(TARGET): links include/list.h $(OBJS) $(APP_O) arch_lib $(LD) -r $(LDFLAGS) $(HEAD_OBJ) $(APP_O) $(OBJS) $(LDARCHLIB) $(LDLIBS) -o $@.o $(OBJCOPY) -w -G $(GLOBAL_PREFIX)* -G _start $@.o $@.o $(LD) $(LDFLAGS) $(LDFLAGS_FINAL) $@.o $(EXTRA_OBJS) -o $@ +ifeq ($(XEN_TARGET_ARCH),arm32) + $(OBJCOPY) -O binary $@ $@.img +else gzip -f -9 -c $@ >$@.gz +endif .PHONY: clean arch_clean diff --git a/extras/mini-os/arch/arm/Makefile b/extras/mini-os/arch/arm/Makefile new file mode 100755 index 0000000..d8ecc88 --- /dev/null +++ b/extras/mini-os/arch/arm/Makefile @@ -0,0 +1,33 @@ +# +# x86 architecture specific makefiles. +# It's is used for x86_32, x86_32y and x86_64 +# + +XEN_ROOT = $(CURDIR)/../../../.. +include $(XEN_ROOT)/Config.mk +include ../../Config.mk + +# include arch.mk has to be before mini-os.mk! + +include arch.mk +include ../../minios.mk + +# Sources here are all *.c *.S without $(XEN_TARGET_ARCH).S +# This is handled in $(HEAD_ARCH_OBJ) +ARCH_SRCS := $(wildcard *.c) + +# The objects built from the sources. +ARCH_OBJS := $(patsubst %.c,$(OBJ_DIR)/%.o,$(ARCH_SRCS)) + +ARCH_OBJS += hypercalls32.o divsi3.o ldivmod.o + +all: $(OBJ_DIR)/$(ARCH_LIB) + +# $(HEAD_ARCH_OBJ) is only build here, needed on linking +# in ../../Makefile. +$(OBJ_DIR)/$(ARCH_LIB): $(ARCH_OBJS) $(OBJ_DIR)/$(HEAD_ARCH_OBJ) + $(AR) rv $(OBJ_DIR)/$(ARCH_LIB) $(ARCH_OBJS) + +clean: + rm -f $(OBJ_DIR)/$(ARCH_LIB) $(ARCH_OBJS) $(OBJ_DIR)/$(HEAD_ARCH_OBJ) + diff --git a/extras/mini-os/arch/arm/arch.mk b/extras/mini-os/arch/arm/arch.mk new file mode 100644 index 0000000..d2e0946 --- /dev/null +++ b/extras/mini-os/arch/arm/arch.mk @@ -0,0 +1,6 @@ +ifeq ($(XEN_TARGET_ARCH),arm32) +ARCH_CFLAGS := -march=armv7-a -marm -fms-extensions -D__arm__ #-DCPU_EXCLUSIVE_LDST +EXTRA_INC += $(TARGET_ARCH_FAM)/$(XEN_TARGET_ARCH) +EXTRA_SRC += arch/$(EXTRA_INC) +endif + diff --git a/extras/mini-os/arch/arm/arm32.S b/extras/mini-os/arch/arm/arm32.S new file mode 100644 index 0000000..2dd0f6c --- /dev/null +++ b/extras/mini-os/arch/arm/arm32.S @@ -0,0 +1,211 @@ +#define PHYS_START (0x80008000) + +.section .text + +.globl _start +_start: + @ zImage header +.rept 8 + mov r0, r0 +.endr + b 1f + .word 0x016f2818 @ Magic numbers to help the loader + .word _start @ absolute load/run zImage address + .word _end - _start @ zImage size + @ end of zImage header + +1: +#if FIXME +@ core processor specific initialization + @ Initialize ACTLR core register + mrc p15, 0, <Rt>, c1, c0, 1 + mcr p15, 0, <Rt>, c1, c0, 1 +#endif + +@ Save dtb pointer passed by the hypervisor + mov r4, r2 @ save dtb pointer + +@ Build pagetables + bl build_pagetables + + ldr r2, =page_dir + MCR p15, 0, r2, c2, c0, 0 @ set ttbr0 + + @ Set access permission for domains + mov r0, #0x3 + MCR p15, 0, r0, c3, c0, 0 + isb + + ldr r0, =mmu_switched + + @ enable mmu / sctlr + mrc p15, 0, r1, c1, c0, 0 @ read sctlr + orr r1, r1, #0x1 @ enable mmu + @orr r1, r1, #0x4 @ enable cache + orr r1, r1, #0x02 @ enable barrier enable + @mcr p15, 0, r1, c1, c0, 0 @ write sctlr + isb + + @ jump to the virtual address now + mov pc, r0 + +@ If we're here, then we're very lucky +mmu_switched: + +@ set VBAR = exception_vector_table + @ SCTLR.V = 0 + adr r0, exception_vector_table + mcr p15, 0, r0, c12, c0, 0 + +@ load stack + ldr sp, =stack + add sp, sp, #(4*4*1024) + + + mov r0, r4 @ set r0 = dtb pointer + b arch_init + + +@ Populate the whole pagedir with 1MB section descriptors for now (1-1 mapping) +build_pagetables: + ldr r0, =(0x2 + (1 << 16) + (1<<19)) @ First section entry (sharable + NS ). + ldr r1, =page_dir + add r2, r1, #(4*4*1024) @ Limit + +1: + str r0, [r1] @ write the section entry + + add r0, r0, #(1 << 20) @ next physical page. + add r1, r1, #4 @ next pagedir entry + cmp r1, r2 + bne 1b + + mov pc, lr + +.pushsection .data +.align 13 +.globl stack +stack: + .fill (4*1024), 4, 0x0 +.align 13 +irqstack: + .fill (1024), 4, 0x0 +.globl shared_info_page +.align 13 +shared_info_page: + .fill (1024), 4, 0x0 +.align 14 +page_dir: + .fill (4*1024), 4, 0x0 + +.popsection + +@ exception base address +.align 5 +.globl exception_vector_table +exception_vector_table: + b . @ reset + b . @ undefined instruction + b . @ supervisor call + b . @ prefetch call + b . @ prefetch abort + b . @ data abort //FIXME CLREX + b irq_handler @ irq + b firq_handler @ firq + +irq_handler: +firq_handler: + ldr sp, =irqstack + add sp, sp, #(4*1024) + + @ Save registers + stmda sp!, {r0 - r12} + stmda sp!, {lr} + + @ FIXME Find interrupt id and dispatch to the correct handler. + @ If event_irq + ldr r0, IRQ_handler + cmp r0, #0 + beq . @ If no IRQ handler was setup, just get stuck here! + + adr lr, 1f + mov pc, r0 +1: + @bl do_hypervisor_callback + + @ Restore registers + ldmib sp!, {lr} + ldmib sp!, {r0 - r12} + + @ Return from IRQ + subs pc, lr, #4 + +.globl IRQ_handler +IRQ_handler: + .long 0x0 + + +.globl __arch_switch_threads +@ r0 = &prev->sp & r1 = &(next->sp) +__arch_switch_threads: + @ store sp, ip for prev thread + str sp, [r0] @ sp + str lr, [r0, #4] @ ip + str fp, [sp, #-4] @ store fp on the stack + @ Load sp, ip for next thread + ldr sp, [r1] @ sp + ldr lr, [r1, #4] @ ip + ldr fp, [sp, #-4] @ restore fp from the stack + mov pc, lr + +#if 0 +pagetables_code: + bl build_pagetables + + ldr r2, =(page_dir+PHYS_START) + MCR p15, 0, r2, c2, c0, 0 @ set ttbr0 + + @ Set access permission for domains + mov r0, #0x3 + MCR p15, 0, r0, c3, c0, 0 + + ldr r0, =mmu_switched + + @ enable mmu / sctlr + isb + MRC p15, 0, r1, c1, c0, 0 @ read sctlr + orr r1, r1, #0x1 + MCR p15, 0, r1, c1, c0, 0 @ write sctlr + MRC p15, 0, r1, c0, c0, 0 @ read id reg + + @ jump to the virtual address now + mov pc, r0 + +mmu_switched: + b . + +build_pagetables: + ldr r2, =(page_dir + PHYS_START) + ldr r0, =(pagetable + PHYS_START + 1) + str r0, [r2] + + ldr r2, =(pagetable + PHYS_START) + add r1, r2, #1000 + + @ setup entry + ldr r0, =(PHYS_START + 0x3) +2: + str r0, [r2], #4 + add r0, r0, #1 << 12 + cmp r2, r1 + bne 2b + mov pc, lr + +.pushsection .data +.align 14 +page_dir: + .fill (1024), 4, 0x0 +pagetable: + .fill (1024*50), 4, 0x0 +.popsection +#endif diff --git a/extras/mini-os/arch/arm/divsi3.S b/extras/mini-os/arch/arm/divsi3.S new file mode 100644 index 0000000..fa92233 --- /dev/null +++ b/extras/mini-os/arch/arm/divsi3.S @@ -0,0 +1,404 @@ +/* $NetBSD: divsi3.S,v 1.4 2003/04/05 23:27:15 bjh21 Exp $ */ + +/*- + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#define ENTRY_NP(symbol) \ + .globl symbol; \ + symbol: + +#define END(symbol) + +/* + * stack is aligned as there's a possibility of branching to L_overflow + * which makes a C call + */ + +ENTRY_NP(__umodsi3) + stmfd sp!, {lr} + sub sp, sp, #4 /* align stack */ + bl .L_udivide + add sp, sp, #4 /* unalign stack */ + mov r0, r1 + ldmfd sp!, {pc} +END(__umodsi3) + +ENTRY_NP(__modsi3) + stmfd sp!, {lr} + sub sp, sp, #4 /* align stack */ + bl .L_divide + add sp, sp, #4 /* unalign stack */ + mov r0, r1 + ldmfd sp!, {pc} + +.L_overflow: + /* XXX should cause a fatal error */ + mvn r0, #0 + mov pc, lr + +END(__modsi3) + +#ifdef __ARM_EABI__ +ENTRY_NP(__aeabi_uidiv) +ENTRY_NP(__aeabi_uidivmod) +#endif +ENTRY_NP(__udivsi3) +.L_udivide: /* r0 = r0 / r1; r1 = r0 % r1 */ + eor r0, r1, r0 + eor r1, r0, r1 + eor r0, r1, r0 + /* r0 = r1 / r0; r1 = r1 % r0 */ + cmp r0, #1 + bcc .L_overflow + beq .L_divide_l0 + mov ip, #0 + movs r1, r1 + bpl .L_divide_l1 + orr ip, ip, #0x20000000 /* ip bit 0x20000000 = -ve r1 */ + movs r1, r1, lsr #1 + orrcs ip, ip, #0x10000000 /* ip bit 0x10000000 = bit 0 of r1 */ + b .L_divide_l1 + +.L_divide_l0: /* r0 == 1 */ + mov r0, r1 + mov r1, #0 + mov pc, lr +#ifdef __ARM_EABI__ +END(__aeabi_uidiv) +END(__aeabi_uidivmod) +#endif +END(__udivsi3) + +#ifdef __ARM_EABI__ +ENTRY_NP(__aeabi_idiv) +ENTRY_NP(__aeabi_idivmod) +#endif +ENTRY_NP(__divsi3) +.L_divide: /* r0 = r0 / r1; r1 = r0 % r1 */ + eor r0, r1, r0 + eor r1, r0, r1 + eor r0, r1, r0 + /* r0 = r1 / r0; r1 = r1 % r0 */ + cmp r0, #1 + bcc .L_overflow + beq .L_divide_l0 + ands ip, r0, #0x80000000 + rsbmi r0, r0, #0 + ands r2, r1, #0x80000000 + eor ip, ip, r2 + rsbmi r1, r1, #0 + orr ip, r2, ip, lsr #1 /* ip bit 0x40000000 = -ve division */ + /* ip bit 0x80000000 = -ve remainder */ + +.L_divide_l1: + mov r2, #1 + mov r3, #0 + + /* + * If the highest bit of the dividend is set, we have to be + * careful when shifting the divisor. Test this. + */ + movs r1,r1 + bpl .L_old_code + + /* + * At this point, the highest bit of r1 is known to be set. + * We abuse this below in the tst instructions. + */ + tst r1, r0 /*, lsl #0 */ + bmi .L_divide_b1 + tst r1, r0, lsl #1 + bmi .L_divide_b2 + tst r1, r0, lsl #2 + bmi .L_divide_b3 + tst r1, r0, lsl #3 + bmi .L_divide_b4 + tst r1, r0, lsl #4 + bmi .L_divide_b5 + tst r1, r0, lsl #5 + bmi .L_divide_b6 + tst r1, r0, lsl #6 + bmi .L_divide_b7 + tst r1, r0, lsl #7 + bmi .L_divide_b8 + tst r1, r0, lsl #8 + bmi .L_divide_b9 + tst r1, r0, lsl #9 + bmi .L_divide_b10 + tst r1, r0, lsl #10 + bmi .L_divide_b11 + tst r1, r0, lsl #11 + bmi .L_divide_b12 + tst r1, r0, lsl #12 + bmi .L_divide_b13 + tst r1, r0, lsl #13 + bmi .L_divide_b14 + tst r1, r0, lsl #14 + bmi .L_divide_b15 + tst r1, r0, lsl #15 + bmi .L_divide_b16 + tst r1, r0, lsl #16 + bmi .L_divide_b17 + tst r1, r0, lsl #17 + bmi .L_divide_b18 + tst r1, r0, lsl #18 + bmi .L_divide_b19 + tst r1, r0, lsl #19 + bmi .L_divide_b20 + tst r1, r0, lsl #20 + bmi .L_divide_b21 + tst r1, r0, lsl #21 + bmi .L_divide_b22 + tst r1, r0, lsl #22 + bmi .L_divide_b23 + tst r1, r0, lsl #23 + bmi .L_divide_b24 + tst r1, r0, lsl #24 + bmi .L_divide_b25 + tst r1, r0, lsl #25 + bmi .L_divide_b26 + tst r1, r0, lsl #26 + bmi .L_divide_b27 + tst r1, r0, lsl #27 + bmi .L_divide_b28 + tst r1, r0, lsl #28 + bmi .L_divide_b29 + tst r1, r0, lsl #29 + bmi .L_divide_b30 + tst r1, r0, lsl #30 + bmi .L_divide_b31 +/* + * instead of: + * tst r1, r0, lsl #31 + * bmi .L_divide_b32 + */ + b .L_divide_b32 + +.L_old_code: + cmp r1, r0 + bcc .L_divide_b0 + cmp r1, r0, lsl #1 + bcc .L_divide_b1 + cmp r1, r0, lsl #2 + bcc .L_divide_b2 + cmp r1, r0, lsl #3 + bcc .L_divide_b3 + cmp r1, r0, lsl #4 + bcc .L_divide_b4 + cmp r1, r0, lsl #5 + bcc .L_divide_b5 + cmp r1, r0, lsl #6 + bcc .L_divide_b6 + cmp r1, r0, lsl #7 + bcc .L_divide_b7 + cmp r1, r0, lsl #8 + bcc .L_divide_b8 + cmp r1, r0, lsl #9 + bcc .L_divide_b9 + cmp r1, r0, lsl #10 + bcc .L_divide_b10 + cmp r1, r0, lsl #11 + bcc .L_divide_b11 + cmp r1, r0, lsl #12 + bcc .L_divide_b12 + cmp r1, r0, lsl #13 + bcc .L_divide_b13 + cmp r1, r0, lsl #14 + bcc .L_divide_b14 + cmp r1, r0, lsl #15 + bcc .L_divide_b15 + cmp r1, r0, lsl #16 + bcc .L_divide_b16 + cmp r1, r0, lsl #17 + bcc .L_divide_b17 + cmp r1, r0, lsl #18 + bcc .L_divide_b18 + cmp r1, r0, lsl #19 + bcc .L_divide_b19 + cmp r1, r0, lsl #20 + bcc .L_divide_b20 + cmp r1, r0, lsl #21 + bcc .L_divide_b21 + cmp r1, r0, lsl #22 + bcc .L_divide_b22 + cmp r1, r0, lsl #23 + bcc .L_divide_b23 + cmp r1, r0, lsl #24 + bcc .L_divide_b24 + cmp r1, r0, lsl #25 + bcc .L_divide_b25 + cmp r1, r0, lsl #26 + bcc .L_divide_b26 + cmp r1, r0, lsl #27 + bcc .L_divide_b27 + cmp r1, r0, lsl #28 + bcc .L_divide_b28 + cmp r1, r0, lsl #29 + bcc .L_divide_b29 + cmp r1, r0, lsl #30 + bcc .L_divide_b30 +.L_divide_b32: + cmp r1, r0, lsl #31 + subhs r1, r1,r0, lsl #31 + addhs r3, r3,r2, lsl #31 +.L_divide_b31: + cmp r1, r0, lsl #30 + subhs r1, r1,r0, lsl #30 + addhs r3, r3,r2, lsl #30 +.L_divide_b30: + cmp r1, r0, lsl #29 + subhs r1, r1,r0, lsl #29 + addhs r3, r3,r2, lsl #29 +.L_divide_b29: + cmp r1, r0, lsl #28 + subhs r1, r1,r0, lsl #28 + addhs r3, r3,r2, lsl #28 +.L_divide_b28: + cmp r1, r0, lsl #27 + subhs r1, r1,r0, lsl #27 + addhs r3, r3,r2, lsl #27 +.L_divide_b27: + cmp r1, r0, lsl #26 + subhs r1, r1,r0, lsl #26 + addhs r3, r3,r2, lsl #26 +.L_divide_b26: + cmp r1, r0, lsl #25 + subhs r1, r1,r0, lsl #25 + addhs r3, r3,r2, lsl #25 +.L_divide_b25: + cmp r1, r0, lsl #24 + subhs r1, r1,r0, lsl #24 + addhs r3, r3,r2, lsl #24 +.L_divide_b24: + cmp r1, r0, lsl #23 + subhs r1, r1,r0, lsl #23 + addhs r3, r3,r2, lsl #23 +.L_divide_b23: + cmp r1, r0, lsl #22 + subhs r1, r1,r0, lsl #22 + addhs r3, r3,r2, lsl #22 +.L_divide_b22: + cmp r1, r0, lsl #21 + subhs r1, r1,r0, lsl #21 + addhs r3, r3,r2, lsl #21 +.L_divide_b21: + cmp r1, r0, lsl #20 + subhs r1, r1,r0, lsl #20 + addhs r3, r3,r2, lsl #20 +.L_divide_b20: + cmp r1, r0, lsl #19 + subhs r1, r1,r0, lsl #19 + addhs r3, r3,r2, lsl #19 +.L_divide_b19: + cmp r1, r0, lsl #18 + subhs r1, r1,r0, lsl #18 + addhs r3, r3,r2, lsl #18 +.L_divide_b18: + cmp r1, r0, lsl #17 + subhs r1, r1,r0, lsl #17 + addhs r3, r3,r2, lsl #17 +.L_divide_b17: + cmp r1, r0, lsl #16 + subhs r1, r1,r0, lsl #16 + addhs r3, r3,r2, lsl #16 +.L_divide_b16: + cmp r1, r0, lsl #15 + subhs r1, r1,r0, lsl #15 + addhs r3, r3,r2, lsl #15 +.L_divide_b15: + cmp r1, r0, lsl #14 + subhs r1, r1,r0, lsl #14 + addhs r3, r3,r2, lsl #14 +.L_divide_b14: + cmp r1, r0, lsl #13 + subhs r1, r1,r0, lsl #13 + addhs r3, r3,r2, lsl #13 +.L_divide_b13: + cmp r1, r0, lsl #12 + subhs r1, r1,r0, lsl #12 + addhs r3, r3,r2, lsl #12 +.L_divide_b12: + cmp r1, r0, lsl #11 + subhs r1, r1,r0, lsl #11 + addhs r3, r3,r2, lsl #11 +.L_divide_b11: + cmp r1, r0, lsl #10 + subhs r1, r1,r0, lsl #10 + addhs r3, r3,r2, lsl #10 +.L_divide_b10: + cmp r1, r0, lsl #9 + subhs r1, r1,r0, lsl #9 + addhs r3, r3,r2, lsl #9 +.L_divide_b9: + cmp r1, r0, lsl #8 + subhs r1, r1,r0, lsl #8 + addhs r3, r3,r2, lsl #8 +.L_divide_b8: + cmp r1, r0, lsl #7 + subhs r1, r1,r0, lsl #7 + addhs r3, r3,r2, lsl #7 +.L_divide_b7: + cmp r1, r0, lsl #6 + subhs r1, r1,r0, lsl #6 + addhs r3, r3,r2, lsl #6 +.L_divide_b6: + cmp r1, r0, lsl #5 + subhs r1, r1,r0, lsl #5 + addhs r3, r3,r2, lsl #5 +.L_divide_b5: + cmp r1, r0, lsl #4 + subhs r1, r1,r0, lsl #4 + addhs r3, r3,r2, lsl #4 +.L_divide_b4: + cmp r1, r0, lsl #3 + subhs r1, r1,r0, lsl #3 + addhs r3, r3,r2, lsl #3 +.L_divide_b3: + cmp r1, r0, lsl #2 + subhs r1, r1,r0, lsl #2 + addhs r3, r3,r2, lsl #2 +.L_divide_b2: + cmp r1, r0, lsl #1 + subhs r1, r1,r0, lsl #1 + addhs r3, r3,r2, lsl #1 +.L_divide_b1: + cmp r1, r0 + subhs r1, r1, r0 + addhs r3, r3, r2 +.L_divide_b0: + + tst ip, #0x20000000 + bne .L_udivide_l1 + mov r0, r3 + cmp ip, #0 + rsbmi r1, r1, #0 + movs ip, ip, lsl #1 + bicmi r0, r0, #0x80000000 /* Fix incase we divided 0x80000000 */ + rsbmi r0, r0, #0 + mov pc, lr + +.L_udivide_l1: + tst ip, #0x10000000 + mov r1, r1, lsl #1 + orrne r1, r1, #1 + mov r3, r3, lsl #1 + cmp r1, r0 + subhs r1, r1, r0 + addhs r3, r3, r2 + mov r0, r3 + mov pc, lr +END(__aeabi_idiv) +END(__aeabi_idivmod) +END(__divsi3) + diff --git a/extras/mini-os/arch/arm/events.c b/extras/mini-os/arch/arm/events.c new file mode 100644 index 0000000..6e579e7 --- /dev/null +++ b/extras/mini-os/arch/arm/events.c @@ -0,0 +1,24 @@ +#include <mini-os/os.h> +#include <mini-os/events.h> +#include <mini-os/hypervisor.h> + +static void virq_debug(evtchn_port_t port, struct pt_regs *regs, void *params) +{ + printk("Received a virq_debug event\n"); +} + +evtchn_port_t debug_port = -1; +void arch_init_events(void) { + debug_port = bind_virq(VIRQ_DEBUG, (evtchn_handler_t)virq_debug, 0); + if(debug_port == -1) + BUG(); + unmask_evtchn(debug_port); +} + +void arch_fini_events(void) { + if(debug_port != -1) + { + mask_evtchn(debug_port); + unbind_evtchn(debug_port); + } +} diff --git a/extras/mini-os/arch/arm/hypercalls32.S b/extras/mini-os/arch/arm/hypercalls32.S new file mode 100644 index 0000000..e2f21c4 --- /dev/null +++ b/extras/mini-os/arch/arm/hypercalls32.S @@ -0,0 +1,88 @@ +#define __HYPERVISOR_set_trap_table 0 +#define __HYPERVISOR_mmu_update 1 +#define __HYPERVISOR_set_gdt 2 +#define __HYPERVISOR_stack_switch 3 +#define __HYPERVISOR_set_callbacks 4 +#define __HYPERVISOR_fpu_taskswitch 5 +#define __HYPERVISOR_sched_op_compat 6 /* compat since 0x00030101 */ +#define __HYPERVISOR_platform_op 7 +#define __HYPERVISOR_set_debugreg 8 +#define __HYPERVISOR_get_debugreg 9 +#define __HYPERVISOR_update_descriptor 10 +#define __HYPERVISOR_memory_op 12 +#define __HYPERVISOR_multicall 13 +#define __HYPERVISOR_update_va_mapping 14 +#define __HYPERVISOR_set_timer_op 15 +#define __HYPERVISOR_event_channel_op_compat 16 /* compat since 0x00030202 */ +#define __HYPERVISOR_xen_version 17 +#define __HYPERVISOR_console_io 18 +#define __HYPERVISOR_physdev_op_compat 19 /* compat since 0x00030202 */ +#define __HYPERVISOR_grant_table_op 20 +#define __HYPERVISOR_vm_assist 21 +#define __HYPERVISOR_update_va_mapping_otherdomain 22 +#define __HYPERVISOR_iret 23 /* x86 only */ +#define __HYPERVISOR_vcpu_op 24 +#define __HYPERVISOR_set_segment_base 25 /* x86/64 only */ +#define __HYPERVISOR_mmuext_op 26 +#define __HYPERVISOR_xsm_op 27 +#define __HYPERVISOR_nmi_op 28 +#define __HYPERVISOR_sched_op 29 +#define __HYPERVISOR_callback_op 30 +#define __HYPERVISOR_xenoprof_op 31 +#define __HYPERVISOR_event_channel_op 32 +#define __HYPERVISOR_physdev_op 33 +#define __HYPERVISOR_hvm_op 34 +#define __HYPERVISOR_sysctl 35 +#define __HYPERVISOR_domctl 36 +#define __HYPERVISOR_kexec_op 37 +#define __HYPERVISOR_tmem_op 38 +#define __HYPERVISOR_xc_reserved_op 39 /* reserved for XenClient */ + + + +#define __HVC(imm16) .long ((0xE1400070 | (((imm16) & 0xFFF0) << 4) | ((imm16) & 0x000F)) & 0xFFFFFFFF) + +#define XEN_IMM 0xEA1 + +#define HYPERCALL_SIMPLE(hypercall) \ +.globl HYPERVISOR_##hypercall; \ +.align 4,0x90; \ +HYPERVISOR_##hypercall: \ + mov r12, #__HYPERVISOR_##hypercall; \ + __HVC(XEN_IMM); \ + mov pc, lr; + +#define _hypercall0 HYPERCALL_SIMPLE +#define _hypercall1 HYPERCALL_SIMPLE +#define _hypercall2 HYPERCALL_SIMPLE +#define _hypercall3 HYPERCALL_SIMPLE +#define _hypercall4 HYPERCALL_SIMPLE + +_hypercall1(set_trap_table); +_hypercall4(mmu_update); +_hypercall4(mmuext_op); +_hypercall2(set_gdt); +_hypercall2(stack_switch); +_hypercall3(set_callbacks); +_hypercall1(fpu_taskswitch); +_hypercall2(sched_op); +_hypercall1(set_timer_op); +_hypercall2(set_debugreg); +_hypercall1(get_debugreg); +_hypercall2(update_descriptor); +_hypercall2(memory_op); +_hypercall2(multicall); +_hypercall3(update_va_mapping); +_hypercall2(event_channel_op); +_hypercall2(xen_version); +_hypercall3(console_io); +_hypercall1(physdev_op); +_hypercall3(grant_table_op); +_hypercall4(update_va_mapping_otherdomain); +_hypercall2(vm_assist); +_hypercall3(vcpu_op); +_hypercall2(set_segment_base); +_hypercall2(nmi_op); +_hypercall1(sysctl); +_hypercall1(domctl); +_hypercall2(hvm_op); diff --git a/extras/mini-os/arch/arm/ldivmod.S b/extras/mini-os/arch/arm/ldivmod.S new file mode 100644 index 0000000..7529826 --- /dev/null +++ b/extras/mini-os/arch/arm/ldivmod.S @@ -0,0 +1,67 @@ +/* + * Copyright (C) 2012 Andrew Turner + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +#define ENTRY_NP(symbol) \ + .globl symbol; \ + symbol: + +#define END(symbol) + +/* + * These calculate: + * q = n / m + * With a remainer r. + * + * They take n in {r0, r1} and m in {r2, r3} then pass them into the + * helper function. The hepler functions return q in {r0, r1} as + * required by the API spec however r is returned on the stack. The + * ABI required us to return r in {r2, r3}. + * + * We need to allocate 8 bytes on the stack to store r, the link + * register, and a pointer to the space where the helper function + * will write r to. After returning from the helper fuinction we load + * the old link register and r from the stack and return. + */ +ENTRY_NP(__aeabi_ldivmod) + sub sp, sp, #8 /* Space for the remainder */ + stmfd sp!, {sp, lr} /* Save a pointer to the above space and lr */ + bl __kern_ldivmod + ldr lr, [sp, #4] /* Restore lr */ + add sp, sp, #8 /* Move sp to the remainder value */ + ldmfd sp!, {r2, r3} /* Load the remainder */ + mov pc, lr +END(__aeabi_ldivmod) + +ENTRY_NP(__aeabi_uldivmod) + sub sp, sp, #8 /* Space for the remainder */ + stmfd sp!, {sp, lr} /* Save a pointer to the above space and lr */ + bl __qdivrem + ldr lr, [sp, #4] /* Restore lr */ + add sp, sp, #8 /* Move sp to the remainder value */ + ldmfd sp!, {r2, r3} /* Load the remainder */ + mov pc, lr +END(__aeabi_uldivmod) diff --git a/extras/mini-os/arch/arm/ldivmod_helper.c b/extras/mini-os/arch/arm/ldivmod_helper.c new file mode 100644 index 0000000..f4dde48 --- /dev/null +++ b/extras/mini-os/arch/arm/ldivmod_helper.c @@ -0,0 +1,66 @@ +/* + * Copyright (C) 2012 Andrew Turner + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +#include <mini-os/types.h> + +u_quad_t __qdivrem(u_quad_t u, u_quad_t v, u_quad_t *rem); + +quad_t +__divdi3(quad_t a, quad_t b) +{ + u_quad_t ua, ub, uq; + int neg; + + if (a < 0) + ua = -(u_quad_t)a, neg = 1; + else + ua = a, neg = 0; + if (b < 0) + ub = -(u_quad_t)b, neg ^= 1; + else + ub = b; + uq = __qdivrem(ua, ub, (u_quad_t *)0); + return (neg ? -uq : uq); +} + +/* + * Helper for __aeabi_ldivmod. + * TODO: __divdi3 calls __qdivrem. We should do the same and use the + * remainder value rather than re-calculating it. + */ +long long __kern_ldivmod(long long, long long, long long *); + +long long +__kern_ldivmod(long long n, long long m, long long *rem) +{ + long long q; + + q = __divdi3(n, m); /* q = n / m */ + *rem = n - m * q; + + return q; +} diff --git a/extras/mini-os/arch/arm/minios-arm32.lds b/extras/mini-os/arch/arm/minios-arm32.lds new file mode 100755 index 0000000..793f0de --- /dev/null +++ b/extras/mini-os/arch/arm/minios-arm32.lds @@ -0,0 +1,73 @@ +OUTPUT_ARCH(arm) +ENTRY(_start) +SECTIONS +{ + . = 0x80008000; + _text = .; /* Text and read-only data */ + .text : { + *(.text) + *(.gnu.warning) + } = 0x9090 + + _etext = .; /* End of text section */ + + .rodata : { *(.rodata) *(.rodata.*) } + . = ALIGN(4096); + _erodata = .; + + /* newlib initialization functions */ + . = ALIGN(32 / 8); + PROVIDE (__preinit_array_start = .); + .preinit_array : { *(.preinit_array) } + PROVIDE (__preinit_array_end = .); + PROVIDE (__init_array_start = .); + .init_array : { *(.init_array) } + PROVIDE (__init_array_end = .); + PROVIDE (__fini_array_start = .); + .fini_array : { *(.fini_array) } + PROVIDE (__fini_array_end = .); + + .ctors : { + __CTOR_LIST__ = .; + *(.ctors) + CONSTRUCTORS + LONG(0) + __CTOR_END__ = .; + } + + .dtors : { + __DTOR_LIST__ = .; + *(.dtors) + LONG(0) + __DTOR_END__ = .; + } + + .data : { /* Data */ + *(.data) + } + + _edata = .; /* End of data section */ + + __bss_start = .; /* BSS */ + .bss : { + *(.bss) + *(.app.bss) + } + _end = . ; + + /* Sections to be discarded */ + /DISCARD/ : { + *(.text.exit) + *(.data.exit) + *(.exitcall.exit) + } + + /* Stabs debugging sections. */ + .stab 0 : { *(.stab) } + .stabstr 0 : { *(.stabstr) } + .stab.excl 0 : { *(.stab.excl) } + .stab.exclstr 0 : { *(.stab.exclstr) } + .stab.index 0 : { *(.stab.index) } + .stab.indexstr 0 : { *(.stab.indexstr) } + .comment 0 : { *(.comment) } +} diff --git a/extras/mini-os/arch/arm/mm.c b/extras/mini-os/arch/arm/mm.c new file mode 100644 index 0000000..7e7ff06 --- /dev/null +++ b/extras/mini-os/arch/arm/mm.c @@ -0,0 +1,44 @@ +#include <console.h> +#include <arm/arch_mm.h> + +#define PHYS_START (0x80008000 + (1000 * 4 * 1024)) +#define PHYS_SIZE (40*1024*1024) + +static void build_pagetable(unsigned long *start_pfn, unsigned long *max_pfn) +{ + // FIXME Create small pages descriptors here instead of the 1M superpages created earlier. + return; +} + +unsigned long allocate_ondemand(unsigned long n, unsigned long alignment) +{ + // FIXME + BUG(); +} + +void arch_init_mm(unsigned long* start_pfn_p, unsigned long* max_pfn_p) +{ + printk(" _text: %p(VA)\n", &_text); + printk(" _etext: %p(VA)\n", &_etext); + printk(" _erodata: %p(VA)\n", &_erodata); + printk(" _edata: %p(VA)\n", &_edata); + printk(" stack start: %p(VA)\n", stack); + printk(" _end: %p(VA)\n", &_end); + + // FIXME Get from dt! + *start_pfn_p = (((unsigned long)&_end) >> PAGE_SHIFT) + 1000; + *max_pfn_p = ((unsigned long)&_end + PHYS_SIZE) >> PAGE_SHIFT; + + printk(" start_pfn: %lx\n", *start_pfn_p); + printk(" max_pfn: %lx\n", *max_pfn_p); + + build_pagetable(start_pfn_p, max_pfn_p); +} + +void arch_init_p2m(unsigned long max_pfn) +{ +} + +void arch_init_demand_mapping_area(unsigned long cur_pfn) +{ +} diff --git a/extras/mini-os/arch/arm/qdivrem.c b/extras/mini-os/arch/arm/qdivrem.c new file mode 100644 index 0000000..0ab5733 --- /dev/null +++ b/extras/mini-os/arch/arm/qdivrem.c @@ -0,0 +1,270 @@ +/*- + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This software was developed by the Computer Systems Engineering group + * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and + * contributed to Berkeley. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <mini-os/types.h> + +/* + * Multiprecision divide. This algorithm is from Knuth vol. 2 (2nd ed), + * section 4.3.1, pp. 257--259. + */ + +#define B (1 << HALF_BITS) /* digit base */ + +/* Combine two `digits' to make a single two-digit number. */ +#define COMBINE(a, b) (((u_long)(a) << HALF_BITS) | (b)) + +/* select a type for digits in base B: use unsigned short if they fit */ +#if ULONG_MAX == 0xffffffff && USHRT_MAX >= 0xffff +typedef unsigned short digit; +#else +typedef u_long digit; +#endif + +/* + * Shift p[0]..p[len] left `sh' bits, ignoring any bits that + * `fall out' the left (there never will be any such anyway). + * We may assume len >= 0. NOTE THAT THIS WRITES len+1 DIGITS. + */ +static void +__shl(register digit *p, register int len, register int sh) +{ + register int i; + + for (i = 0; i < len; i++) + p[i] = LHALF(p[i] << sh) | (p[i + 1] >> (HALF_BITS - sh)); + p[i] = LHALF(p[i] << sh); +} + +/* + * __qdivrem(u, v, rem) returns u/v and, optionally, sets *rem to u%v. + * + * We do this in base 2-sup-HALF_BITS, so that all intermediate products + * fit within u_long. As a consequence, the maximum length dividend and + * divisor are 4 `digits' in this base (they are shorter if they have + * leading zeros). + */ +u_quad_t +__qdivrem(u_quad_t uq, u_quad_t vq, u_quad_t *arq) +{ + union uu tmp; + digit *u, *v, *q; + register digit v1, v2; + u_long qhat, rhat, t; + int m, n, d, j, i; + digit uspace[5], vspace[5], qspace[5]; + + /* + * Take care of special cases: divide by zero, and u < v. + */ + if (vq == 0) { + /* divide by zero. */ + static volatile const unsigned int zero = 0; + + tmp.ul[H] = tmp.ul[L] = 1 / zero; + if (arq) + *arq = uq; + return (tmp.q); + } + if (uq < vq) { + if (arq) + *arq = uq; + return (0); + } + u = &uspace[0]; + v = &vspace[0]; + q = &qspace[0]; + + /* + * Break dividend and divisor into digits in base B, then + * count leading zeros to determine m and n. When done, we + * will have: + * u = (u[1]u[2]...u[m+n]) sub B + * v = (v[1]v[2]...v[n]) sub B + * v[1] != 0 + * 1 < n <= 4 (if n = 1, we use a different division algorithm) + * m >= 0 (otherwise u < v, which we already checked) + * m + n = 4 + * and thus + * m = 4 - n <= 2 + */ + tmp.uq = uq; + u[0] = 0; + u[1] = HHALF(tmp.ul[H]); + u[2] = LHALF(tmp.ul[H]); + u[3] = HHALF(tmp.ul[L]); + u[4] = LHALF(tmp.ul[L]); + tmp.uq = vq; + v[1] = HHALF(tmp.ul[H]); + v[2] = LHALF(tmp.ul[H]); + v[3] = HHALF(tmp.ul[L]); + v[4] = LHALF(tmp.ul[L]); + for (n = 4; v[1] == 0; v++) { + if (--n == 1) { + u_long rbj; /* r*B+u[j] (not root boy jim) */ + digit q1, q2, q3, q4; + + /* + * Change of plan, per exercise 16. + * r = 0; + * for j = 1..4: + * q[j] = floor((r*B + u[j]) / v), + * r = (r*B + u[j]) % v; + * We unroll this completely here. + */ + t = v[2]; /* nonzero, by definition */ + q1 = u[1] / t; + rbj = COMBINE(u[1] % t, u[2]); + q2 = rbj / t; + rbj = COMBINE(rbj % t, u[3]); + q3 = rbj / t; + rbj = COMBINE(rbj % t, u[4]); + q4 = rbj / t; + if (arq) + *arq = rbj % t; + tmp.ul[H] = COMBINE(q1, q2); + tmp.ul[L] = COMBINE(q3, q4); + return (tmp.q); + } + } + + /* + * By adjusting q once we determine m, we can guarantee that + * there is a complete four-digit quotient at &qspace[1] when + * we finally stop. + */ + for (m = 4 - n; u[1] == 0; u++) + m--; + for (i = 4 - m; --i >= 0;) + q[i] = 0; + q += 4 - m; + + /* + * Here we run Program D, translated from MIX to C and acquiring + * a few minor changes. + * + * D1: choose multiplier 1 << d to ensure v[1] >= B/2. + */ + d = 0; + for (t = v[1]; t < B / 2; t <<= 1) + d++; + if (d > 0) { + __shl(&u[0], m + n, d); /* u <<= d */ + __shl(&v[1], n - 1, d); /* v <<= d */ + } + /* + * D2: j = 0. + */ + j = 0; + v1 = v[1]; /* for D3 -- note that v[1..n] are constant */ + v2 = v[2]; /* for D3 */ + do { + register digit uj0, uj1, uj2; + + /* + * D3: Calculate qhat (\^q, in TeX notation). + * Let qhat = min((u[j]*B + u[j+1])/v[1], B-1), and + * let rhat = (u[j]*B + u[j+1]) mod v[1]. + * While rhat < B and v[2]*qhat > rhat*B+u[j+2], + * decrement qhat and increase rhat correspondingly. + * Note that if rhat >= B, v[2]*qhat < rhat*B. + */ + uj0 = u[j + 0]; /* for D3 only -- note that u[j+...] change */ + uj1 = u[j + 1]; /* for D3 only */ + uj2 = u[j + 2]; /* for D3 only */ + if (uj0 == v1) { + qhat = B; + rhat = uj1; + goto qhat_too_big; + } else { + u_long nn = COMBINE(uj0, uj1); + qhat = nn / v1; + rhat = nn % v1; + } + while (v2 * qhat > COMBINE(rhat, uj2)) { + qhat_too_big: + qhat--; + if ((rhat += v1) >= B) + break; + } + /* + * D4: Multiply and subtract. + * The variable `t' holds any borrows across the loop. + * We split this up so that we do not require v[0] = 0, + * and to eliminate a final special case. + */ + for (t = 0, i = n; i > 0; i--) { + t = u[i + j] - v[i] * qhat - t; + u[i + j] = LHALF(t); + t = (B - HHALF(t)) & (B - 1); + } + t = u[j] - t; + u[j] = LHALF(t); + /* + * D5: test remainder. + * There is a borrow if and only if HHALF(t) is nonzero; + * in that (rare) case, qhat was too large (by exactly 1). + * Fix it by adding v[1..n] to u[j..j+n]. + */ + if (HHALF(t)) { + qhat--; + for (t = 0, i = n; i > 0; i--) { /* D6: add back. */ + t += u[i + j] + v[i]; + u[i + j] = LHALF(t); + t = HHALF(t); + } + u[j] = LHALF(u[j] + t); + } + q[j] = qhat; + } while (++j <= m); /* D7: loop on j. */ + + /* + * If caller wants the remainder, we have to calculate it as + * u[m..m+n] >> d (this is at most n digits and thus fits in + * u[m+1..m+n], but we may need more source digits). + */ + if (arq) { + if (d) { + for (i = m + n; i > m; --i) + u[i] = (u[i] >> d) | + LHALF(u[i - 1] << (HALF_BITS - d)); + u[i] = 0; + } + tmp.ul[H] = COMBINE(uspace[1], uspace[2]); + tmp.ul[L] = COMBINE(uspace[3], uspace[4]); + *arq = tmp.q; + } + + tmp.ul[H] = COMBINE(qspace[1], qspace[2]); + tmp.ul[L] = COMBINE(qspace[3], qspace[4]); + return (tmp.q); +} diff --git a/extras/mini-os/arch/arm/sched.c b/extras/mini-os/arch/arm/sched.c new file mode 100644 index 0000000..e490105 --- /dev/null +++ b/extras/mini-os/arch/arm/sched.c @@ -0,0 +1,32 @@ +#include <mini-os/sched.h> +#include <mini-os/xmalloc.h> + + +/* Architecture specific setup of thread creation */ +struct thread* arch_create_thread(char *name, void (*function)(void *), + void *data) +{ + struct thread *thread; + + thread = xmalloc(struct thread); + /* We can't use lazy allocation here since the trap handler runs on the stack */ + thread->stack = (char *)alloc_pages(STACK_SIZE_PAGE_ORDER); + thread->name = name; + printk("Thread \"%s\": pointer: 0x%lx, stack: 0x%lx\n", name, thread, + thread->stack); + + thread->sp = (unsigned long)thread->stack + STACK_SIZE; + /* Save pointer to the thread on the stack, used by current macro */ + *((unsigned long *)thread->stack) = (unsigned long)thread; + + thread->ip = (unsigned long) function; + /* FIXME thread->r0 = (unsigned long)data; */ + + return thread; +} + +void run_idle_thread(void) +{ + __asm__ __volatile__ ("mov sp, %0; mov pc, %1"::"r"(idle_thread->sp), "r"(idle_thread->ip)); + /* Never arrive here! */ +} diff --git a/extras/mini-os/arch/arm/setup.c b/extras/mini-os/arch/arm/setup.c new file mode 100644 index 0000000..f0b2f47 --- /dev/null +++ b/extras/mini-os/arch/arm/setup.c @@ -0,0 +1,55 @@ +#include <mini-os/os.h> +#include <xen/xen.h> +#include <xen/memory.h> +#include <hypervisor.h> +#include <arm/arch_mm.h> + +/* + * This structure contains start-of-day info, such as pagetable base pointer, + * address of the shared_info structure, and things like that. + */ +union start_info_union start_info_union; + +/* + * Shared page for communicating with the hypervisor. + * Events flags go here, for example. + */ +shared_info_t *HYPERVISOR_shared_info; + +extern char shared_info_page[PAGE_SIZE]; + +void start_kernel(void); + +/* + * INITIAL C ENTRY POINT. + */ +void arch_init(void *dtb_pointer) +{ + struct xen_add_to_physmap xatp; + + memset(&__bss_start, 0, &_end - &__bss_start); + + printk("dtb_pointer : %x\n", dtb_pointer); + + /* Map shared_info page */ + xatp.domid = DOMID_SELF; + xatp.idx = 0; + xatp.space = XENMAPSPACE_shared_info; + xatp.gpfn = virt_to_pfn(shared_info_page); + if (HYPERVISOR_memory_op(XENMEM_add_to_physmap, &xatp) != 0) + BUG(); + HYPERVISOR_shared_info = (struct shared_info *)shared_info_page; + + start_kernel(); +} + +void +arch_fini(void) +{ + +} + +void +arch_do_exit(void) +{ +} diff --git a/extras/mini-os/arch/arm/time.c b/extras/mini-os/arch/arm/time.c new file mode 100644 index 0000000..6dba1fe --- /dev/null +++ b/extras/mini-os/arch/arm/time.c @@ -0,0 +1,232 @@ +#include <mini-os/os.h> +#include <mini-os/hypervisor.h> +#include <mini-os/events.h> +#include <mini-os/traps.h> +#include <mini-os/types.h> +#include <mini-os/time.h> +#include <mini-os/lib.h> + +//#define VTIMER_DEBUG +#ifdef VTIMER_DEBUG +#define DEBUG(_f, _a...) \ + printk("MINI_OS(file=vtimer.c, line=%d) " _f , __LINE__, ## _a) +#else +#define DEBUG(_f, _a...) ((void)0) +#endif + + +/************************************************************************ + * Time functions + *************************************************************************/ + +/* These are peridically updated in shared_info, and then copied here. */ +struct shadow_time_info { + uint64_t tsc_timestamp; /* TSC at last update of time vals. */ + uint64_t system_timestamp; /* Time, in nanosecs, since boot. */ + uint32_t tsc_to_nsec_mul; + uint32_t tsc_to_usec_mul; + int tsc_shift; + uint32_t version; +}; +static struct timespec shadow_ts; +static uint32_t shadow_ts_version; + +static struct shadow_time_info shadow; + +#define HANDLE_USEC_OVERFLOW(_tv) \ + do { \ + while ( (_tv)->tv_usec >= 1000000 ) \ + { \ + (_tv)->tv_usec -= 1000000; \ + (_tv)->tv_sec++; \ + } \ + } while ( 0 ) + +static inline int time_values_up_to_date(void) +{ + struct vcpu_time_info *src = &HYPERVISOR_shared_info->vcpu_info[0].time; + + return (shadow.version == src->version); +} + + +/* + * Scale a 64-bit delta by scaling and multiplying by a 32-bit fraction, + * yielding a 64-bit result. + */ +static inline uint64_t scale_delta(uint64_t delta, uint32_t mul_frac, int shift) +{ + BUG(); + return 0; +} + + +static unsigned long get_nsec_offset(void) +{ + return 0; +#if FIXME + uint64_t now, delta; + rdtscll(now); + delta = now - shadow.tsc_timestamp; + return scale_delta(delta, shadow.tsc_to_nsec_mul, shadow.tsc_shift); +#endif +} + + +static void get_time_values_from_xen(void) +{ + struct vcpu_time_info *src = &HYPERVISOR_shared_info->vcpu_info[0].time; + + do { + shadow.version = src->version; + rmb(); + shadow.tsc_timestamp = src->tsc_timestamp; + shadow.system_timestamp = src->system_time; + shadow.tsc_to_nsec_mul = src->tsc_to_system_mul; + shadow.tsc_shift = src->tsc_shift; + rmb(); + } + while ((src->version & 1) | (shadow.version ^ src->version)); + + shadow.tsc_to_usec_mul = shadow.tsc_to_nsec_mul / 1000; +} + + + + +/* monotonic_clock(): returns # of nanoseconds passed since time_init() + * Note: This function is required to return accurate + * time even in the absence of multiple timer ticks. + */ +uint64_t monotonic_clock(void) +{ + uint64_t time; + uint32_t local_time_version; + + do { + local_time_version = shadow.version; + rmb(); + time = shadow.system_timestamp + get_nsec_offset(); + if (!time_values_up_to_date()) + get_time_values_from_xen(); + rmb(); + } while (local_time_version != shadow.version); + + return time; +} + +static void update_wallclock(void) +{ + shared_info_t *s = HYPERVISOR_shared_info; + + do { + shadow_ts_version = s->wc_version; + rmb(); + shadow_ts.tv_sec = s->wc_sec; + shadow_ts.tv_nsec = s->wc_nsec; + rmb(); + } + while ((s->wc_version & 1) | (shadow_ts_version ^ s->wc_version)); +} + + +int gettimeofday(struct timeval *tv, void *tz) +{ + uint64_t nsec = monotonic_clock(); + nsec += shadow_ts.tv_nsec; + + + tv->tv_sec = shadow_ts.tv_sec; + tv->tv_sec += NSEC_TO_SEC(nsec); + tv->tv_usec = NSEC_TO_USEC(nsec % 1000000000UL); + + return 0; +} + + +void block_domain(s_time_t until) +{ + struct timeval tv; + gettimeofday(&tv, NULL); + ASSERT(irqs_disabled()); + if(monotonic_clock() < until) + { + HYPERVISOR_set_timer_op(until); + HYPERVISOR_sched_op(SCHEDOP_block, 0); + local_irq_disable(); + } +} + + +/* + * Just a dummy + */ +void timer_handler(evtchn_port_t port, struct pt_regs *regs, void *ign) +{ + DEBUG("Timer kick\n"); + get_time_values_from_xen(); + update_wallclock(); +} + +#define VTIMER_TICK 0x10000000 +void increment_vtimer_compare(uint64_t inc) { + uint32_t x, y; + uint64_t value; + __asm__ __volatile__("mrrc p15, 1, %0, %1, c14\n" + "isb":"=r"(x), "=r"(y)); + + // CompareValue = Counter + VTIMER_TICK + value = (0xFFFFFFFFFFFFFFFFULL & x) | ((0xFFFFFFFFFFFFFFFFULL & y) << 32); + DEBUG("Counter: %llx(x=%x and y=%x)\n", value, x, y); + value += inc; + DEBUG("New CompareValue : %llx\n", value); + x = 0xFFFFFFFFULL & value; + y = (value >> 32) & 0xFFFFFFFF; + + __asm__ __volatile__("mcrr p15, 3, %0, %1, c14\n" + "isb"::"r"(x), "r"(y)); + + __asm__ __volatile__("mov %0, #0x1\n" + "mcr p15, 0, %0, c14, c3, 1\n" /* Enable timer and unmask the output signal */ + "isb":"=r"(x)); +} + +static inline void enable_virtual_timer(void) { +#if FIXME + uint32_t x, y; + uint64_t value; + + __asm__ __volatile__("ldr %0, =0xffffffff\n" + "ldr %1, =0xffffffff\n" + "dsb\n" + "mcrr p15, 3, %0, %1, c14\n" /* set CompareValue to 0x0000ffff 0000ffff */ + "isb\n" + "mov %0, #0x1\n" + "mcr p15, 0, %0, c14, c3, 1\n" /* Enable timer and unmask the output signal */ + "isb":"=r"(x), "=r"(y)); +#else + increment_vtimer_compare(VTIMER_TICK); +#endif +} + +evtchn_port_t timer_port = -1; +void arch_init_time(void) +{ + // FIXME: VIRQ_TIMER isn't supported under ARM, use ARM Generic Timer instead. + printk("Initialising timer interface\n"); + timer_port = bind_virq(VIRQ_TIMER, (evtchn_handler_t)timer_handler, 0); + if(timer_port == -1) + BUG(); + unmask_evtchn(timer_port); + + enable_virtual_timer(); +} + +void arch_fini_time(void) +{ + if(timer_port != -1) + { + mask_evtchn(timer_port); + unbind_evtchn(timer_port); + } +} diff --git a/extras/mini-os/arch/arm/xenbus.c b/extras/mini-os/arch/arm/xenbus.c new file mode 100644 index 0000000..76feabc --- /dev/null +++ b/extras/mini-os/arch/arm/xenbus.c @@ -0,0 +1,36 @@ +#include <mini-os/os.h> +#include <mini-os/mm.h> +#include <xen/hvm/params.h> +#include <xen/io/xs_wire.h> +#include <mini-os/hypervisor.h> + +static inline int hvm_get_parameter(int idx, uint64_t *value) +{ + struct xen_hvm_param xhv; + int ret; + + xhv.domid = DOMID_SELF; + xhv.index = idx; + ret = HYPERVISOR_hvm_op(HVMOP_get_param, &xhv); + if (ret < 0) { + BUG(); + } + *value = xhv.value; + return ret; +} + +void arch_init_xenbus(struct xenstore_domain_interface **xenstore_buf, uint32_t *store_evtchn) { + uint64_t value; + uint64_t xenstore_pfn; + + if (hvm_get_parameter(HVM_PARAM_STORE_EVTCHN, &value)) + BUG(); + + *store_evtchn = (int)value; + + if(hvm_get_parameter(HVM_PARAM_STORE_PFN, &value)) + BUG(); + xenstore_pfn = (unsigned long)value; + + *xenstore_buf = pfn_to_virt(xenstore_pfn); +} diff --git a/extras/mini-os/arch/x86/events.c b/extras/mini-os/arch/x86/events.c new file mode 100644 index 0000000..87f8b77 --- /dev/null +++ b/extras/mini-os/arch/x86/events.c @@ -0,0 +1,28 @@ +#include <mini-os/os.h> +#include <mini-os/mm.h> + +#if defined(__x86_64__) +char irqstack[2 * STACK_SIZE]; + +static struct pda +{ + int irqcount; /* offset 0 (used in x86_64.S) */ + char *irqstackptr; /* 8 */ +} cpu0_pda; +#endif + +void arch_init_events(void) { +#if defined(__x86_64__) + asm volatile("movl %0,%%fs ; movl %0,%%gs" :: "r" (0)); + wrmsrl(0xc0000101, &cpu0_pda); /* 0xc0000101 is MSR_GS_BASE */ + cpu0_pda.irqcount = -1; + cpu0_pda.irqstackptr = (void*) (((unsigned long)irqstack + 2 * STACK_SIZE) + & ~(STACK_SIZE - 1)); +#endif +} + +void arch_fini_events(void) { +#if defined(__x86_64__) + wrmsrl(0xc0000101, NULL); /* 0xc0000101 is MSR_GS_BASE */ +#endif +} diff --git a/extras/mini-os/arch/x86/setup.c b/extras/mini-os/arch/x86/setup.c index 54046d3..6bb6d4b 100644 --- a/extras/mini-os/arch/x86/setup.c +++ b/extras/mini-os/arch/x86/setup.c @@ -28,6 +28,7 @@ #include <mini-os/os.h> #include <mini-os/lib.h> /* for printk, memcpy */ +#include <xen/xen.h> /* * Shared page for communicating with the hypervisor. @@ -87,14 +88,40 @@ static inline void sse_init(void) { #define sse_init() #endif + +void start_kernel(void); + +/* + * INITIAL C ENTRY POINT. + */ void arch_init(start_info_t *si) { + static char hello[] = "Bootstrapping...\n"; + + (void)HYPERVISOR_console_io(CONSOLEIO_write, strlen(hello), hello); + + trap_init(); + + /* print out some useful information */ + printk("Xen Minimal OS!\n"); + printk(" start_info: %p(VA)\n", si); + printk(" nr_pages: 0x%lx\n", si->nr_pages); + printk(" shared_inf: 0x%08lx(MA)\n", si->shared_info); + printk(" pt_base: %p(VA)\n", (void *)si->pt_base); + printk("nr_pt_frames: 0x%lx\n", si->nr_pt_frames); + printk(" mfn_list: %p(VA)\n", (void *)si->mfn_list); + printk(" mod_start: 0x%lx(VA)\n", si->mod_start); + printk(" mod_len: %lu\n", si->mod_len); + printk(" flags: 0x%x\n", (unsigned int)si->flags); + printk(" cmd_line: %s\n", + si->cmd_line ? (const char *)si->cmd_line : "NULL"); + /*Initialize floating point unit */ - fpu_init(); + fpu_init(); - /* Initialize SSE */ - sse_init(); + /* Initialize SSE */ + sse_init(); /* Copy the start_info struct to a globally-accessible area. */ /* WARN: don't do printk before here, it uses information from @@ -118,12 +145,15 @@ arch_init(start_info_t *si) (unsigned long)failsafe_callback, 0); #endif - + start_kernel(); } void arch_fini(void) { + /* Reset traps */ + trap_fini(); + #ifdef __i386__ HYPERVISOR_set_callbacks(0, 0, 0, 0); #else @@ -132,9 +162,7 @@ arch_fini(void) } void -arch_print_info(void) +arch_do_exit(void) { - printk(" stack: %p-%p\n", stack, stack + sizeof(stack)); + stack_walk(); } - - diff --git a/extras/mini-os/arch/x86/time.c b/extras/mini-os/arch/x86/time.c index 2c8d033..c57ee55 100644 --- a/extras/mini-os/arch/x86/time.c +++ b/extras/mini-os/arch/x86/time.c @@ -223,14 +223,14 @@ static void timer_handler(evtchn_port_t ev, struct pt_regs *regs, void *ign) static evtchn_port_t port; -void init_time(void) +void arch_init_time(void) { printk("Initialising timer interface\n"); port = bind_virq(VIRQ_TIMER, &timer_handler, NULL); unmask_evtchn(port); } -void fini_time(void) +void arch_fini_time(void) { /* Clear any pending timer */ HYPERVISOR_set_timer_op(0); diff --git a/extras/mini-os/arch/x86/x86_32.S b/extras/mini-os/arch/x86/x86_32.S index fb3e30a..b9aa392 100644 --- a/extras/mini-os/arch/x86/x86_32.S +++ b/extras/mini-os/arch/x86/x86_32.S @@ -20,7 +20,7 @@ _start: lss stack_start,%esp andl $(~(__STACK_SIZE-1)), %esp push %esi - call start_kernel + call arch_init stack_start: .long stack+(2*__STACK_SIZE), __KERNEL_SS diff --git a/extras/mini-os/arch/x86/x86_64.S b/extras/mini-os/arch/x86/x86_64.S index f022eb3..df3469e 100644 --- a/extras/mini-os/arch/x86/x86_64.S +++ b/extras/mini-os/arch/x86/x86_64.S @@ -21,7 +21,7 @@ _start: movq stack_start(%rip),%rsp andq $(~(__STACK_SIZE-1)), %rsp movq %rsi,%rdi - call start_kernel + call arch_init stack_start: .quad stack+(2*__STACK_SIZE) diff --git a/extras/mini-os/arch/x86/xenbus.c b/extras/mini-os/arch/x86/xenbus.c new file mode 100644 index 0000000..5cda78d --- /dev/null +++ b/extras/mini-os/arch/x86/xenbus.c @@ -0,0 +1,10 @@ +#include <mini-os/os.h> +#include <mini-os/mm.h> +#include <mini-os/xmalloc.h> +#include <xen/xen.h> +#include <xen/io/xs_wire.h> + +void arch_init_xenbus(struct xenstore_domain_interface **xenstore_buf, uint32_t *store_evtchn) { + *xenstore_buf = mfn_to_virt(start_info.store_mfn); + *store_evtchn = start_info.store_evtchn; +} diff --git a/extras/mini-os/console/console.c b/extras/mini-os/console/console.c index 5538bd4..c08fea9 100644 --- a/extras/mini-os/console/console.c +++ b/extras/mini-os/console/console.c @@ -157,7 +157,9 @@ void xprintk(const char *fmt, ...) void init_console(void) { printk("Initialising console ... "); +#ifndef __arm__ xencons_ring_init(); +#endif console_initialised = 1; /* This is also required to notify the daemon */ printk("done.\n"); diff --git a/extras/mini-os/drivers/gic.c b/extras/mini-os/drivers/gic.c new file mode 100644 index 0000000..14301ae --- /dev/null +++ b/extras/mini-os/drivers/gic.c @@ -0,0 +1,179 @@ +// ARM GIC implementation + +#include <mini-os/os.h> +#include <mini-os/hypervisor.h> + +//#define VGIC_DEBUG +#ifdef VGIC_DEBUG +#define DEBUG(_f, _a...) \ + DEBUG("MINI_OS(file=vgic.c, line=%d) " _f , __LINE__, ## _a) +#else +#define DEBUG(_f, _a...) ((void)0) +#endif + +extern unsigned long IRQ_handler; + +struct gic { + volatile char *gicd_base; + volatile char *gicc_base; +}; + +static struct gic gic; + +// Distributor Interface +#define GICD_CTLR 0x0 +#define GICD_ISENABLER 0x100 +#define GICD_PRIORITY 0x400 +#define GICD_ITARGETSR 0x800 +#define GICD_ICFGR 0xC00 + +// CPU Interface +#define GICC_CTLR 0x0 +#define GICC_PMR 0x4 +#define GICC_IAR 0xc +#define GICC_EOIR 0x10 +#define GICC_HPPIR 0x18 + +#define gicd(gic, offset) ((gic)->gicd_base + (offset)) +#define gicc(gic, offset) ((gic)->gicc_base + (offset)) + +#define REG(addr) ((uint32_t *)(addr)) + +static inline uint32_t REG_READ32(volatile uint32_t *addr) +{ + uint32_t value; + __asm__ __volatile__("ldr %0, [%1]":"=&r"(value):"r"(addr)); + rmb(); + return value; +} + +static inline void REG_WRITE32(volatile uint32_t *addr, unsigned int value) +{ + __asm__ __volatile__("str %0, [%1]"::"r"(value), "r"(addr)); + wmb(); +} + +static void gic_set_priority(struct gic *gic, unsigned char irq_number, unsigned char priority) +{ + uint32_t value; + value = REG_READ32(REG(gicd(gic, GICD_PRIORITY)) + irq_number); + value &= ~(0xff << (8 * (irq_number & 0x3))); // set priority to '0' + value |= priority << (8 * (irq_number & 0x3)); // add our priority + REG_WRITE32(REG(gicd(gic, GICD_PRIORITY)) + irq_number, value); +} + +static void gic_route_interrupt(struct gic *gic, unsigned char irq_number, unsigned char cpu_set) +{ + uint32_t value; + value = REG_READ32(REG(gicd(gic, GICD_ITARGETSR)) + irq_number); + value &= ~(0xff << (8 * (irq_number & 0x3))); // set priority to '0' + value |= cpu_set << (8 * (irq_number & 0x3)); // add our priority + REG_WRITE32(REG(gicd(gic, GICD_ITARGETSR)) + irq_number, value); +} + +static void gic_enable_interrupt(struct gic *gic, unsigned char irq_number, + unsigned char cpu_set, unsigned char level_sensitive, unsigned char ppi) +{ + void *set_enable_reg; + void *cfg_reg; + + // set priority + gic_set_priority(gic, irq_number, 0x0); + + // set target cpus for this interrupt + gic_route_interrupt(gic, irq_number, cpu_set); + + // set level/edge triggered + cfg_reg = (void *)gicd(gic, GICD_ICFGR); + level_sensitive ? clear_bit((irq_number * 2) + 1, cfg_reg) : set_bit((irq_number * 2) + 1, cfg_reg); + if(ppi) + clear_bit((irq_number * 2), cfg_reg); + + wmb(); + + // enable forwarding interrupt from distributor to cpu interface + set_enable_reg = (void *)gicd(gic, GICD_ISENABLER); + set_bit(irq_number, set_enable_reg); + wmb(); +} + +static void gic_enable_interrupts(struct gic *gic) +{ + // Global enable forwarding interrupts from distributor to cpu interface + REG_WRITE32(REG(gicd(gic, GICD_CTLR)), 0x00000001); + + // Global enable signalling of interrupt from the cpu interface + REG_WRITE32(REG(gicc(gic, GICC_CTLR)), 0x00000001); +} + +static void gic_disable_interrupts(struct gic *gic) +{ + // Global disable signalling of interrupt from the cpu interface + REG_WRITE32(REG(gicc(gic, GICC_CTLR)), 0x00000000); + + // Global disable forwarding interrupts from distributor to cpu interface + REG_WRITE32(REG(gicd(gic, GICD_CTLR)), 0x00000000); +} + +static void gic_cpu_set_priority(struct gic *gic, char priority) +{ + REG_WRITE32(REG(gicc(gic, GICC_PMR)), priority & 0x000000FF); +} + +static void gic_set_handler(unsigned long gic_handler) { + IRQ_handler = gic_handler; +} + +static unsigned long gic_readiar(struct gic *gic) { + return REG_READ32(REG(gicc(gic, GICC_IAR))) & 0x000003FF; // Interrupt ID +} + +static void gic_eoir(struct gic *gic, uint32_t irq) { + REG_WRITE32(REG(gicc(gic, GICC_EOIR)), irq & 0x000003FF); +} + +//FIXME Get event_irq from dt +#define EVENTS_IRQ 31 +#define VIRTUALTIMER_IRQ 27 + +//FIXME Move to a header file +#define VTIMER_TICK 0x6000000 +void timer_handler(evtchn_port_t port, struct pt_regs *regs, void *ign); +void increment_vtimer_compare(uint64_t inc); + +static void gic_handler(void) { + unsigned int irq = gic_readiar(&gic); + + DEBUG("IRQ received : %i\n", irq); + switch(irq) { + case EVENTS_IRQ: + do_hypervisor_callback(NULL); + break; + case VIRTUALTIMER_IRQ: + timer_handler(0, NULL, 0); + increment_vtimer_compare(VTIMER_TICK); + break; + default: + DEBUG("Unhandled irq\n"); + break; + } + + DEBUG("EIRQ\n"); + + gic_eoir(&gic, irq); +} + +void gic_init(void) { + // FIXME Get from dt! + gic.gicd_base = (char *)0x2c001000ULL; + gic.gicc_base = (char *)0x2c002000ULL; + wmb(); + + gic_set_handler((unsigned long)gic_handler); + + gic_disable_interrupts(&gic); + gic_cpu_set_priority(&gic, 0xff); + gic_enable_interrupt(&gic, EVENTS_IRQ /* interrupt number */, 0x1 /*cpu_set*/, 1 /*level_sensitive*/, 0 /* ppi */); + gic_enable_interrupt(&gic, VIRTUALTIMER_IRQ /* interrupt number */, 0x1 /*cpu_set*/, 1 /*level_sensitive*/, 1 /* ppi */); + gic_enable_interrupts(&gic); +} diff --git a/extras/mini-os/events.c b/extras/mini-os/events.c index 2da9b01..84a30a3 100644 --- a/extras/mini-os/events.c +++ b/extras/mini-os/events.c @@ -47,9 +47,11 @@ void unbind_all_ports(void) for ( i = 0; i < NR_EVS; i++ ) { +#ifndef __arm__ if ( i == start_info.console.domU.evtchn || i == start_info.store_evtchn) continue; +#endif if ( test_and_clear_bit(i, bound_ports) ) { @@ -167,44 +169,30 @@ evtchn_port_t bind_pirq(uint32_t pirq, int will_share, return op.port; } -#if defined(__x86_64__) -char irqstack[2 * STACK_SIZE]; - -static struct pda -{ - int irqcount; /* offset 0 (used in x86_64.S) */ - char *irqstackptr; /* 8 */ -} cpu0_pda; -#endif - +void arch_init_events(void); /* * Initially all events are without a handler and disabled */ void init_events(void) { int i; -#if defined(__x86_64__) - asm volatile("movl %0,%%fs ; movl %0,%%gs" :: "r" (0)); - wrmsrl(0xc0000101, &cpu0_pda); /* 0xc0000101 is MSR_GS_BASE */ - cpu0_pda.irqcount = -1; - cpu0_pda.irqstackptr = (void*) (((unsigned long)irqstack + 2 * STACK_SIZE) - & ~(STACK_SIZE - 1)); -#endif + /* initialize event handler */ for ( i = 0; i < NR_EVS; i++ ) { ev_actions[i].handler = default_handler; mask_evtchn(i); } + + arch_init_events(); } +void arch_fini_events(void); void fini_events(void) { /* Dealloc all events */ unbind_all_ports(); -#if defined(__x86_64__) - wrmsrl(0xc0000101, NULL); /* 0xc0000101 is MSR_GS_BASE */ -#endif + arch_fini_events(); } void default_handler(evtchn_port_t port, struct pt_regs *regs, void *ignore) @@ -262,7 +250,8 @@ int evtchn_bind_interdomain(domid_t pal, evtchn_port_t remote_port, int evtchn_get_peercontext(evtchn_port_t local_port, char *ctx, int size) { - int rc; + int rc = 0; +#ifndef __arm__ uint32_t sid; struct xen_flask_op op; op.cmd = FLASK_GET_PEER_SID; @@ -277,6 +266,7 @@ int evtchn_get_peercontext(evtchn_port_t local_port, char *ctx, int size) op.u.sid_context.size = size; set_xen_guest_handle(op.u.sid_context.context, ctx); rc = _hypercall1(int, xsm_op, &op); +#endif return rc; } diff --git a/extras/mini-os/gntmap.c b/extras/mini-os/gntmap.c index 7eb69be..abfbd29 100644 --- a/extras/mini-os/gntmap.c +++ b/extras/mini-os/gntmap.c @@ -37,6 +37,7 @@ #include <xen/grant_table.h> #include <inttypes.h> #include <mini-os/gntmap.h> +#include <mini-os/hypervisor.h> //#define GNTMAP_DEBUG #ifdef GNTMAP_DEBUG diff --git a/extras/mini-os/gnttab.c b/extras/mini-os/gnttab.c index 2f1b3d7..404d72c 100644 --- a/extras/mini-os/gnttab.c +++ b/extras/mini-os/gnttab.c @@ -19,6 +19,7 @@ #include <mini-os/mm.h> #include <mini-os/gnttab.h> #include <mini-os/semaphore.h> +#include <mini-os/hypervisor.h> #define NR_RESERVED_ENTRIES 8 diff --git a/extras/mini-os/hypervisor.c b/extras/mini-os/hypervisor.c index b4688a0..9c79d5d 100644 --- a/extras/mini-os/hypervisor.c +++ b/extras/mini-os/hypervisor.c @@ -71,23 +71,6 @@ void do_hypervisor_callback(struct pt_regs *regs) in_callback = 0; } -void force_evtchn_callback(void) -{ - int save; - vcpu_info_t *vcpu; - vcpu = &HYPERVISOR_shared_info->vcpu_info[smp_processor_id()]; - save = vcpu->evtchn_upcall_mask; - - while (vcpu->evtchn_upcall_pending) { - vcpu->evtchn_upcall_mask = 1; - barrier(); - do_hypervisor_callback(NULL); - barrier(); - vcpu->evtchn_upcall_mask = save; - barrier(); - }; -} - inline void mask_evtchn(uint32_t port) { shared_info_t *s = HYPERVISOR_shared_info; @@ -110,8 +93,7 @@ inline void unmask_evtchn(uint32_t port) &vcpu_info->evtchn_pending_sel) ) { vcpu_info->evtchn_upcall_pending = 1; - if ( !vcpu_info->evtchn_upcall_mask ) - force_evtchn_callback(); + force_evtchn_callback(); } } diff --git a/extras/mini-os/include/arm/arch_limits.h b/extras/mini-os/include/arm/arch_limits.h new file mode 100644 index 0000000..bae99e1 --- /dev/null +++ b/extras/mini-os/include/arm/arch_limits.h @@ -0,0 +1,9 @@ +#ifndef __ARCH_LIMITS_H__ +#define __ARCH_LIMITS_H__ + +#include <mm.h> + +#define __STACK_SIZE_PAGE_ORDER 2 +#define __STACK_SIZE (4 * PAGE_SIZE) + +#endif diff --git a/extras/mini-os/include/arm/arch_mm.h b/extras/mini-os/include/arm/arch_mm.h new file mode 100644 index 0000000..9b2cc03 --- /dev/null +++ b/extras/mini-os/include/arm/arch_mm.h @@ -0,0 +1,37 @@ +#ifndef _ARCH_MM_H_ +#define _ARCH_MM_H_ + +extern char _text, _etext, _erodata, _edata, _end, __bss_start; +extern char stack[]; + +#define PAGE_SHIFT 12 +#define PAGE_SIZE (1 << PAGE_SHIFT) +#define PAGE_MASK (~(PAGE_SIZE-1)) + +#define L1_PAGETABLE_SHIFT 12 + +#if 0 +#define VIRT_START ((unsigned long)&_text) +#else +#define VIRT_START ((unsigned long)0) +#endif + +#define to_phys(x) ((unsigned long)(x)-VIRT_START) +#define to_virt(x) ((void *)((unsigned long)(x)+VIRT_START)) + +#define PFN_UP(x) (((x) + PAGE_SIZE-1) >> L1_PAGETABLE_SHIFT) +#define PFN_DOWN(x) ((x) >> L1_PAGETABLE_SHIFT) +#define PFN_PHYS(x) ((uint64_t)(x) << L1_PAGETABLE_SHIFT) +#define PHYS_PFN(x) ((x) >> L1_PAGETABLE_SHIFT) + +#define virt_to_pfn(_virt) (PFN_DOWN(to_phys(_virt))) +#define virt_to_mfn(_virt) (0) +#define mach_to_virt(_mach) (0) +#define virt_to_mach(_virt) (0) +#define mfn_to_virt(_mfn) (0) +#define pfn_to_virt(_pfn) (to_virt(PFN_PHYS(_pfn))) + +// FIXME +#define map_frames(f, n) (NULL) + +#endif diff --git a/extras/mini-os/include/arm/arch_sched.h b/extras/mini-os/include/arm/arch_sched.h new file mode 100644 index 0000000..31d9071 --- /dev/null +++ b/extras/mini-os/include/arm/arch_sched.h @@ -0,0 +1,22 @@ + +#ifndef __ARCH_SCHED_H__ +#define __ARCH_SCHED_H__ + +#include "arch_limits.h" + +static inline struct thread* get_current(void) +{ + struct thread **current; + unsigned long sp; + __asm__ __volatile__ ("mov %0, sp":"=r"(sp)); + current = (void *)(unsigned long)(sp & ~(__STACK_SIZE-1)); + return *current; +} + + +extern void __arch_switch_threads(unsigned long *prevctx, unsigned long *nextctx); + +#define arch_switch_threads(prev,next) __arch_switch_threads(&(prev)->sp, &(next)->sp) + + +#endif /* __ARCH_SCHED_H__ */ diff --git a/extras/mini-os/include/arm/arch_spinlock.h b/extras/mini-os/include/arm/arch_spinlock.h new file mode 100755 index 0000000..6677bc4 --- /dev/null +++ b/extras/mini-os/include/arm/arch_spinlock.h @@ -0,0 +1,49 @@ + + +#ifndef __ARCH_ASM_SPINLOCK_H +#define __ARCH_ASM_SPINLOCK_H + +#include "os.h" + + +#define ARCH_SPIN_LOCK_UNLOCKED { 1 } + +/* + * Simple spin lock operations. There are two variants, one clears IRQ's + * on the local processor, one does not. + * + * We make no fairness assumptions. They have a cost. + */ + +#define arch_spin_is_locked(x) (*(volatile signed char *)(&(x)->slock) <= 0) +#define arch_spin_unlock_wait(x) do { barrier(); } while(spin_is_locked(x)) + +/* + * This works. Despite all the confusion. + * (except on PPro SMP or if we are using OOSTORE) + * (PPro errata 66, 92) + */ + +static inline void _raw_spin_unlock(spinlock_t *lock) +{ + xchg(&lock->slock, 1); +} + +static inline int _raw_spin_trylock(spinlock_t *lock) +{ + return xchg(&lock->slock, 0) != 0 ? 1 : 0; +} + +static inline void _raw_spin_lock(spinlock_t *lock) +{ + volatile int was_locked; + do { + was_locked = xchg(&lock->slock, 0) == 0 ? 1 : 0; + } while(was_locked); +} + +static inline void _raw_spin_lock_flags (spinlock_t *lock, unsigned long flags) +{ +} + +#endif diff --git a/extras/mini-os/include/arm/hypercall-arm32.h b/extras/mini-os/include/arm/hypercall-arm32.h new file mode 100644 index 0000000..0343946 --- /dev/null +++ b/extras/mini-os/include/arm/hypercall-arm32.h @@ -0,0 +1,173 @@ +/****************************************************************************** + * hypercall-x86_64.h + * + * Copied from XenLinux. + * + * Copyright (c) 2002-2004, K A Fraser + * + * 64-bit updates: + * Benjamin Liu <benjamin.liu@xxxxxxxxx> + * Jun Nakajima <jun.nakajima@xxxxxxxxx> + * + * This file may be distributed separately from the Linux kernel, or + * incorporated into other software packages, subject to the following license: + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this source file (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, modify, + * merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#ifndef __HYPERCALL_ARM_H__ +#define __HYPERCALL_ARM_H__ + +#include <xen/xen.h> +#include <xen/sched.h> +#include <mini-os/mm.h> + +inline int +HYPERVISOR_mmu_update( + mmu_update_t *req, int count, int *success_count, domid_t domid); + +inline int +HYPERVISOR_mmuext_op( + struct mmuext_op *op, int count, int *success_count, domid_t domid); + +inline int +HYPERVISOR_set_gdt( + unsigned long *frame_list, int entries); + +inline int +HYPERVISOR_stack_switch( + unsigned long ss, unsigned long esp); + +inline int +HYPERVISOR_set_callbacks( + unsigned long event_address, unsigned long failsafe_address, + unsigned long syscall_address); + +inline int +HYPERVISOR_fpu_taskswitch( + int set); + +inline int +HYPERVISOR_sched_op( + int cmd, void *arg); + +static inline int +HYPERVISOR_shutdown( + unsigned int reason) +{ + struct sched_shutdown shutdown = { .reason = reason }; + return low_shutdown(&shutdown); +} + +inline long +HYPERVISOR_set_timer_op( + uint64_t timeout); + +inline int +HYPERVISOR_set_debugreg( + int reg, unsigned long value); + +inline unsigned long +HYPERVISOR_get_debugreg( + int reg); + +inline int +HYPERVISOR_update_descriptor( + unsigned long ma, unsigned long word); + +inline int +HYPERVISOR_memory_op( + unsigned int cmd, void *arg); + +inline int +HYPERVISOR_multicall( + void *call_list, int nr_calls); + +inline int +HYPERVISOR_update_va_mapping( + unsigned long va, pte_t new_val, unsigned long flags); + +inline int +HYPERVISOR_event_channel_op( + int cmd, void *op); + +inline int +HYPERVISOR_xen_version( + int cmd, void *arg); + +inline int +HYPERVISOR_console_io( + int cmd, int count, char *str); + +inline int +HYPERVISOR_physdev_op( + void *physdev_op); + +inline int +HYPERVISOR_grant_table_op( + unsigned int cmd, void *uop, unsigned int count); + +inline int +HYPERVISOR_update_va_mapping_otherdomain( + unsigned long va, pte_t new_val, unsigned long flags, domid_t domid); + +inline int +HYPERVISOR_vm_assist( + unsigned int cmd, unsigned int type); + +inline int +HYPERVISOR_vcpu_op( + int cmd, int vcpuid, void *extra_args); + +inline int +HYPERVISOR_set_segment_base( + int reg, unsigned long value); + +inline int +HYPERVISOR_suspend( + unsigned long srec); + +inline int +HYPERVISOR_nmi_op( + unsigned long op, + unsigned long arg); + +inline int +HYPERVISOR_sysctl( + unsigned long op); + +inline int +HYPERVISOR_domctl( + unsigned long op); + +inline int +HYPERVISOR_hvm_op( + unsigned long op, void *arg); + +#endif /* __HYPERCALL_X86_64_H__ */ + +/* + * Local variables: + * c-file-style: "linux" + * indent-tabs-mode: t + * c-indent-level: 8 + * c-basic-offset: 8 + * tab-width: 8 + * End: + */ diff --git a/extras/mini-os/include/arm/os.h b/extras/mini-os/include/arm/os.h new file mode 100644 index 0000000..60e84f7 --- /dev/null +++ b/extras/mini-os/include/arm/os.h @@ -0,0 +1,314 @@ +#ifndef _OS_H_ +#define _OS_H_ + +#ifndef __ASSEMBLY__ + +#include <mini-os/types.h> +#include <xen/xen.h> + +void arch_fini(void); + +#define BUG() while(1){} + +#define smp_processor_id() 0 + +#define barrier() __asm__ __volatile__("": : :"memory") + +extern shared_info_t *HYPERVISOR_shared_info; + +#if 0 +static inline void force_evtchn_callback(void) +{ + int save; + vcpu_info_t *vcpu; + vcpu = &HYPERVISOR_shared_info->vcpu_info[smp_processor_id()]; + save = vcpu->evtchn_upcall_mask; + + while (vcpu->evtchn_upcall_pending) { + vcpu->evtchn_upcall_mask = 1; + barrier(); + do_hypervisor_callback(NULL); + barrier(); + vcpu->evtchn_upcall_mask = save; + barrier(); + }; +} +#else +#define force_evtchn_callback(void) do {} while(0) +#endif + +// disable interrupts +static inline __cli(void) { + int x; + __asm__ __volatile__("mrs %0, cpsr;cpsid i":"=r"(x)::"memory"); +} + +// enable interrupts +static inline __sti(void) { + int x; + __asm__ __volatile__("mrs %0, cpsr\n" + "bic %0, %0, #0x80\n" + "msr cpsr_c, %0" + :"=r"(x)::"memory"); +} + +static inline int irqs_disabled() { + int x; + __asm__ __volatile__("mrs %0, cpsr\n":"=r"(x)::"memory"); + return (x & 0x80); +} + +#define local_irq_save(x) { \ + __asm__ __volatile__("mrs %0, cpsr;cpsid i; and %0, %0, #0x80":"=r"(x)::"memory"); \ +} + +#define local_irq_restore(x) { \ + __asm__ __volatile__("msr cpsr_c, %0"::"r"(x):"memory"); \ +} + +#define local_save_flags(x) { \ + __asm__ __volatile__("mrs %0, cpsr; and %0, %0, 0x80":"=r"(x)::"memory"); \ +} + +#define local_irq_disable() __cli() +#define local_irq_enable() __sti() + +#if defined(__arm__) +#define mb() __asm__("dmb"); +#define rmb() __asm__("dmb"); +#define wmb() __asm__("dmb"); +#elif defined(__aarch64__) +#define mb() +#define rmb() +#define wmb() +#else +#error undefined architecture +#endif + +#define LOCK_PREFIX "" +#define LOCK "" + +#define unlikely(x) __builtin_expect((x),0) +#define likely(x) __builtin_expect((x),1) + +#define ADDR (*(volatile long *) addr) + +/************************** arm *******************************/ +#ifdef __INSIDE_MINIOS__ +#if defined (__arm__) +#define xchg(ptr,v) ((__typeof__(*(ptr)))__xchg((unsigned long)(v),(ptr),sizeof(*(ptr)))) +#define __xg(x) ((volatile long *)(x)) + +static inline unsigned long __xchg(unsigned long x, volatile void * ptr, int size) +{ + //TODO + unsigned volatile long y, tmp = 0; + switch(size){ + case 1: +#if CPU_EXCLUSIVE_LDST + __asm__ __volatile__("1:ldrexb %0, [%1]\n" + "strexb %3, %2, [%1]\n" + "cmp %3, #1\n" + "beq 1b\n\n" + "dmb\n":"=&r"(y):"r"(ptr), "r"(x), "r"(tmp):"memory"); +#else + y = (*(char *)ptr) & 0x000000ff; + *((char *)ptr) = (char)x; +#endif + break; + case 2: +#if CPU_EXCLUSIVE_LDST + __asm__ __volatile__("1:ldrexh %0, [%1]\n" + "strexh %3, %2, [%1]\n" + "cmp %3, #1\n" + "beq 1b\n\n" + "dmb\n":"=&r"(y):"r"(ptr), "r"(x), "r"(tmp):"memory"); +#else + y = (*(short *)ptr) & 0x0000ffff; + *((short *)ptr) = (short)x; +#endif + break; + default: // 4 +#if CPU_EXCLUSIVE_LDST + __asm__ __volatile__("1:ldrex %0, [%1]\n" + "strex %3, %2, [%1]\n" + "cmp %3, #1\n" + "beq 1b\n\n" + "dmb\n":"=&r"(y):"r"(ptr), "r"(x), "r"(tmp):"memory"); +#else + y = (*(unsigned long *)ptr) & 0xffffffff; + *((unsigned long *)ptr) = x; +#endif + break; + } + return y; +} + +/** + * test_and_clear_bit - Clear a bit and return its old value + * @nr: Bit to clear + * @addr: Address to count from + * + * This operation is atomic and cannot be reordered. + * It also implies a memory barrier. + */ +static __inline__ int test_and_clear_bit(int nr, volatile void * addr) +{ + //TODO + unsigned long *tmp = (unsigned long *)addr; + + int x = tmp[nr >> 5] & (1 << (nr & 0x1f)); + tmp[nr >> 5] &= ~(1 << (nr & 0x1f)); + return x; +} + +static __inline__ int test_and_set_bit(int nr, volatile void * addr) +{ + //TODO + unsigned long *tmp = (unsigned long *)addr; + + int x = tmp[nr >> 5] & (1 << (nr & 0x1f)); + tmp[nr >> 5] |= (1 << (nr & 0x1f)); + return x; +} + +static __inline__ int constant_test_bit(int nr, const volatile void * addr) +{ + //TODO + unsigned long *tmp = (unsigned long *)addr; + return tmp[nr >> 5] & (1 << (nr & 0x1f)); +} + +static __inline__ int variable_test_bit(int nr, volatile const void * addr) +{ + //TODO: + unsigned long *tmp = (unsigned long *)addr; + return tmp[nr >> 5] & (1 << (nr & 0x1f)); +} + +//TODO +#define test_bit(nr,addr) (((unsigned long *)addr)[nr >> 5] & (1 << (nr & 0x1f))) + + +/** + * set_bit - Atomically set a bit in memory + * @nr: the bit to set + * @addr: the address to start counting from + * + * This function is atomic and may not be reordered. See __set_bit() + * if you do not require the atomic guarantees. + * Note that @nr may be almost arbitrarily large; this function is not + * restricted to acting on a single-word quantity. + */ +static __inline__ void set_bit(int nr, volatile void * addr) +{ + //TODO: + unsigned long *tmp = (unsigned long *)addr; + tmp[nr >> 5] |= (1 << (nr & 0x1f)); +} + +/** + * clear_bit - Clears a bit in memory + * @nr: Bit to clear + * @addr: Address to start counting from + * + * clear_bit() is atomic and may not be reordered. However, it does + * not contain a memory barrier, so if it is used for locking purposes, + * you should call smp_mb__before_clear_bit() and/or smp_mb__after_clear_bit() + * in order to ensure changes are visible on other processors. + */ +static __inline__ void clear_bit(int nr, volatile void * addr) +{ + //TODO + unsigned long *tmp = (unsigned long *)addr; + tmp[nr >> 5] &= (unsigned long)~(1 << (nr & 0x1f)); +} + +/** + * __ffs - find first bit in word. + * @word: The word to search + * + * Undefined if no bit exists, so code should check against 0 first. + */ +static __inline__ unsigned long __ffs(unsigned long word) +{ + //TODO + int index = 0; + while(!(word & (1 << index++))){}; + + return index - 1; +} + +//FIXME +#define rdtscll(val) (val = 0) + +#define wrmsr(msr,val1,val2) (0) + +#define wrmsrl(msr,val) wrmsr(msr,(uint32_t)((uint64_t)(val)),((uint64_t)(val))>>32) + + +#else /* ifdef __arm__ */ +#error "Unsupported architecture" +#endif +#endif /* ifdef __INSIDE_MINIOS */ + +/********************* common arm32 and arm64 ****************************/ +struct __synch_xchg_dummy { unsigned long a[100]; }; +#define __synch_xg(x) ((struct __synch_xchg_dummy *)(x)) + +#define synch_cmpxchg(ptr, old, new) (0) + +static inline unsigned long __synch_cmpxchg(volatile void *ptr, + unsigned long old, + unsigned long new, int size) +{ + //TODO: + //BUG(); + return 0; +} + + +static __inline__ void synch_set_bit(int nr, volatile void * addr) +{ + //TODO: + set_bit(nr, addr); +} + +static __inline__ void synch_clear_bit(int nr, volatile void * addr) +{ + //TODO: + clear_bit(nr, addr); +} + +static __inline__ int synch_test_and_set_bit(int nr, volatile void * addr) +{ + //TODO: + return test_and_set_bit(nr, addr); +} + +static __inline__ int synch_test_and_clear_bit(int nr, volatile void * addr) +{ + //TODO: + return test_and_clear_bit(nr, addr); +} + +static __inline__ int synch_const_test_bit(int nr, const volatile void * addr) +{ + //TODO: + return const_test_bit(nr, addr); +} + +static __inline__ int synch_var_test_bit(int nr, volatile void * addr) +{ + //TODO: + return var_test_bit(nr, addr); +} + +#define synch_test_bit(nr,addr) test_bit(nr, addr) + + +#undef ADDR + +#endif /* not assembly */ + +#endif diff --git a/extras/mini-os/include/arm/traps.h b/extras/mini-os/include/arm/traps.h new file mode 100644 index 0000000..b8ce784 --- /dev/null +++ b/extras/mini-os/include/arm/traps.h @@ -0,0 +1,20 @@ +#ifndef _TRAPS_H_ +#define _TRAPS_H_ + +struct pt_regs { + unsigned long r0; + unsigned long r1; + unsigned long r2; + unsigned long r3; + unsigned long r4; + unsigned long r5; + unsigned long r6; + unsigned long r7; + unsigned long r8; + unsigned long r9; + unsigned long r10; + unsigned long r11; + unsigned long r12; +}; + +#endif diff --git a/extras/mini-os/include/console.h b/extras/mini-os/include/console.h index 3755b66..dade8fb 100644 --- a/extras/mini-os/include/console.h +++ b/extras/mini-os/include/console.h @@ -42,6 +42,7 @@ #include <xen/grant_table.h> #include <xenbus.h> #include <xen/io/console.h> +#include <xen/event_channel.h> #include <stdarg.h> struct consfront_dev { diff --git a/extras/mini-os/include/hypervisor.h b/extras/mini-os/include/hypervisor.h index a62cb78..ee288a0 100644 --- a/extras/mini-os/include/hypervisor.h +++ b/extras/mini-os/include/hypervisor.h @@ -13,16 +13,34 @@ #define _HYPERVISOR_H_ #include <mini-os/types.h> + #include <xen/xen.h> + #if defined(__i386__) #include <hypercall-x86_32.h> #elif defined(__x86_64__) #include <hypercall-x86_64.h> +#elif defined(__arm__) +#include <hypercall-arm32.h> +#elif defined(__aarch64__) +#include <hypercall-arm64.h> #else #error "Unsupported architecture" #endif #include <mini-os/traps.h> +#ifdef __arm__ +struct start_info { + union { + struct { + xen_pfn_t mfn; + uint32_t evtchn; + } domU; + } console; +}; +typedef struct start_info start_info_t; +#endif + /* * a placeholder for the start of day information passed up from the hypervisor */ @@ -35,7 +53,6 @@ extern union start_info_union start_info_union; #define start_info (start_info_union.start_info) /* hypervisor.c */ -void force_evtchn_callback(void); void do_hypervisor_callback(struct pt_regs *regs); void mask_evtchn(uint32_t port); void unmask_evtchn(uint32_t port); diff --git a/extras/mini-os/include/mm.h b/extras/mini-os/include/mm.h index a94cd6d..644c7de 100644 --- a/extras/mini-os/include/mm.h +++ b/extras/mini-os/include/mm.h @@ -29,6 +29,8 @@ #include <xen/arch-x86_32.h> #elif defined(__x86_64__) #include <xen/arch-x86_64.h> +#elif defined(__arm__) || defined(__aarch64__) +#include <xen/arch-arm.h> #else #error "Unsupported architecture" #endif diff --git a/extras/mini-os/include/types.h b/extras/mini-os/include/types.h index 6640ede..781144c 100644 --- a/extras/mini-os/include/types.h +++ b/extras/mini-os/include/types.h @@ -27,7 +27,7 @@ typedef unsigned char u_char; typedef unsigned int u_int; typedef unsigned long u_long; #endif -#ifdef __i386__ +#if defined(__i386__) || defined(__arm__) typedef long long quad_t; typedef unsigned long long u_quad_t; @@ -40,7 +40,7 @@ typedef unsigned long u_quad_t; typedef struct { unsigned long pte; } pte_t; #endif /* __i386__ || __x86_64__ */ -#ifdef __x86_64__ +#if defined(__x86_64__) || defined(__aarch64__) #define __pte(x) ((pte_t) { (x) } ) #else #define __pte(x) ({ unsigned long long _x = (x); \ @@ -51,10 +51,10 @@ typedef struct { unsigned long pte; } pte_t; #include <limits.h> #include <stdint.h> #else -#ifdef __i386__ +#if defined(__i386__) || defined(__arm__) typedef unsigned int uintptr_t; typedef int intptr_t; -#elif defined(__x86_64__) +#elif defined(__x86_64__) || defined(__aarch64__) typedef unsigned long uintptr_t; typedef long intptr_t; #endif /* __i386__ || __x86_64__ */ @@ -64,10 +64,10 @@ typedef unsigned short uint16_t; typedef signed short int16_t; typedef unsigned int uint32_t; typedef signed int int32_t; -#ifdef __i386__ +#if defined(__i386__) || defined(__arm__) typedef signed long long int64_t; typedef unsigned long long uint64_t; -#elif defined(__x86_64__) +#elif defined(__x86_64__) || defined(__aarch64__) typedef signed long int64_t; typedef unsigned long uint64_t; #endif @@ -83,4 +83,65 @@ typedef intptr_t ptrdiff_t; typedef long ssize_t; #endif +#ifdef __arm__ +/* + * From + * @(#)quad.h 8.1 (Berkeley) 6/4/93 + */ + +#ifdef __BIG_ENDIAN +#define _QUAD_HIGHWORD 0 +#define _QUAD_LOWWORD 1 +#else /* __LITTLE_ENDIAN */ +#define _QUAD_HIGHWORD 1 +#define _QUAD_LOWWORD 0 +#endif + +/* + * Define high and low longwords. + */ +#define H _QUAD_HIGHWORD +#define L _QUAD_LOWWORD + +/* + * Total number of bits in a quad_t and in the pieces that make it up. + * These are used for shifting, and also below for halfword extraction + * and assembly. + */ +#define CHAR_BIT 8 /* number of bits in a char */ +#define QUAD_BITS (sizeof(s64) * CHAR_BIT) +#define LONG_BITS (sizeof(long) * CHAR_BIT) +#define HALF_BITS (sizeof(long) * CHAR_BIT / 2) + +#define B (1 << HALF_BITS) /* digit base */ +/* + * Extract high and low shortwords from longword, and move low shortword of + * longword to upper half of long, i.e., produce the upper longword of + * ((quad_t)(x) << (number_of_bits_in_long/2)). (`x' must actually be u_long.) + * + * These are used in the multiply code, to split a longword into upper + * and lower halves, and to reassemble a product as a quad_t, shifted left + * (sizeof(long)*CHAR_BIT/2). + */ +#define HHALF(x) ((x) >> HALF_BITS) +#define LHALF(x) ((x) & ((1 << HALF_BITS) - 1)) +#define LHUP(x) ((x) << HALF_BITS) + +#define COMBINE(a, b) (((u_long)(a) << HALF_BITS) | (b)) + +/* + * Depending on the desired operation, we view a `long long' (aka quad_t) in + * one or more of the following formats. + */ +union uu { + int64_t q; /* as a (signed) quad */ + int64_t uq; /* as an unsigned quad */ + long sl[2]; /* as two signed longs */ + unsigned long ul[2]; /* as two unsigned longs */ +}; + +/* select a type for digits in base B */ +typedef u_long digit; +#endif + #endif /* _TYPES_H_ */ diff --git a/extras/mini-os/include/x86/arch_mm.h b/extras/mini-os/include/x86/arch_mm.h index 23cfca7..3b74cd7 100644 --- a/extras/mini-os/include/x86/arch_mm.h +++ b/extras/mini-os/include/x86/arch_mm.h @@ -25,6 +25,8 @@ #ifndef _ARCH_MM_H_ #define _ARCH_MM_H_ +extern char stack[]; + #ifndef __ASSEMBLY__ #include <xen/xen.h> #if defined(__i386__) diff --git a/extras/mini-os/include/x86/os.h b/extras/mini-os/include/x86/os.h index f193865..8eea1be 100644 --- a/extras/mini-os/include/x86/os.h +++ b/extras/mini-os/include/x86/os.h @@ -64,8 +64,6 @@ extern shared_info_t *HYPERVISOR_shared_info; void trap_init(void); void trap_fini(void); -void arch_init(start_info_t *si); -void arch_print_info(void); void arch_fini(void); @@ -162,6 +160,23 @@ do { \ */ typedef struct { volatile int counter; } atomic_t; +static inline void force_evtchn_callback(void) +{ + int save; + vcpu_info_t *vcpu; + vcpu = &HYPERVISOR_shared_info->vcpu_info[smp_processor_id()]; + save = vcpu->evtchn_upcall_mask; + + while (vcpu->evtchn_upcall_pending) { + vcpu->evtchn_upcall_mask = 1; + barrier(); + do_hypervisor_callback(NULL); + barrier(); + vcpu->evtchn_upcall_mask = save; + barrier(); + }; +} + /************************** i386 *******************************/ #ifdef __INSIDE_MINIOS__ diff --git a/extras/mini-os/include/x86/x86_64/hypercall-x86_64.h b/extras/mini-os/include/x86/x86_64/hypercall-x86_64.h index 7083763..4581574 100644 --- a/extras/mini-os/include/x86/x86_64/hypercall-x86_64.h +++ b/extras/mini-os/include/x86/x86_64/hypercall-x86_64.h @@ -37,6 +37,7 @@ #include <xen/xen.h> #include <xen/sched.h> #include <mini-os/mm.h> +#include <arch_mm.h> #define __STR(x) #x #define STR(x) __STR(x) diff --git a/extras/mini-os/kernel.c b/extras/mini-os/kernel.c index 386be8f..de25921 100644 --- a/extras/mini-os/kernel.c +++ b/extras/mini-os/kernel.c @@ -27,7 +27,6 @@ * DEALINGS IN THE SOFTWARE. */ -#include <mini-os/os.h> #include <mini-os/hypervisor.h> #include <mini-os/mm.h> #include <mini-os/events.h> @@ -118,40 +117,14 @@ __attribute__((weak)) int app_main(start_info_t *si) return 0; } -/* - * INITIAL C ENTRY POINT. - */ -void start_kernel(start_info_t *si) -{ - static char hello[] = "Bootstrapping...\n"; - - (void)HYPERVISOR_console_io(CONSOLEIO_write, strlen(hello), hello); - - arch_init(si); - - trap_init(); - - /* print out some useful information */ - printk("Xen Minimal OS!\n"); - printk(" start_info: %p(VA)\n", si); - printk(" nr_pages: 0x%lx\n", si->nr_pages); - printk(" shared_inf: 0x%08lx(MA)\n", si->shared_info); - printk(" pt_base: %p(VA)\n", (void *)si->pt_base); - printk("nr_pt_frames: 0x%lx\n", si->nr_pt_frames); - printk(" mfn_list: %p(VA)\n", (void *)si->mfn_list); - printk(" mod_start: 0x%lx(VA)\n", si->mod_start); - printk(" mod_len: %lu\n", si->mod_len); - printk(" flags: 0x%x\n", (unsigned int)si->flags); - printk(" cmd_line: %s\n", - si->cmd_line ? (const char *)si->cmd_line : "NULL"); +void gic_init(void); +void start_kernel(void) +{ /* Set up events. */ init_events(); - - /* ENABLE EVENT DELIVERY. This is disabled at start of day. */ - __sti(); - arch_print_info(); + __sti(); setup_xen_features(); @@ -161,24 +134,58 @@ void start_kernel(start_info_t *si) /* Init time and timers. */ init_time(); +#ifndef __arm__ /* Init the console driver. */ init_console(); +#endif /* Init grant tables */ init_gnttab(); - + /* Init scheduler. */ init_sched(); /* Init XenBus */ init_xenbus(); + #ifdef CONFIG_XENBUS create_thread("shutdown", shutdown_thread, NULL); #endif +#ifdef __arm__ + gic_init(); +#endif + +//#define VTIMER_TEST +#ifdef VTIMER_TEST + while(1){ + int x, y, z; + z = 0; + // counter + __asm__ __volatile__("mrrc p15, 1, %0, %1, c14;isb":"=r"(x), "=r"(y)); + printk("Counter: %x-%x\n", x, y); + + __asm__ __volatile__("mrrc p15, 3, %0, %1, c14;isb":"=r"(x), "=r"(y)); + printk("CompareValue: %x-%x\n", x, y); + + // TimerValue + __asm__ __volatile__("mrc p15, 0, %0, c14, c3, 0;isb":"=r"(x)); + printk("TimerValue: %x\n", x); + + // control register + __asm__ __volatile__("mrc p15, 0, %0, c14, c3, 1;isb":"=r"(x)); + printk("ControlRegister: %x\n", x); + while(z++ < 0xfffff){} + } +#endif + /* Call (possibly overridden) app_main() */ +#if defined(__arm__) || defined(__aarch64__) + app_main(NULL); +#else app_main(&start_info); +#endif /* Everything initialised, start idle thread */ run_idle_thread(); @@ -205,13 +212,12 @@ void stop_kernel(void) /* Reset events. */ fini_events(); - /* Reset traps */ - trap_fini(); - /* Reset arch details */ arch_fini(); } +void arch_do_exit(void); + /* * do_exit: This is called whenever an IRET fails in entry.S. * This will generally be because an application has got itself into @@ -222,7 +228,7 @@ void stop_kernel(void) void do_exit(void) { printk("Do_exit called!\n"); - stack_walk(); + arch_do_exit(); for( ;; ) { struct sched_shutdown sched_shutdown = { .reason = SHUTDOWN_crash }; diff --git a/extras/mini-os/mm.c b/extras/mini-os/mm.c index d2d5264..ab76018 100644 --- a/extras/mini-os/mm.c +++ b/extras/mini-os/mm.c @@ -213,22 +213,26 @@ static void init_page_allocator(unsigned long min, unsigned long max) min = round_pgup (min); max = round_pgdown(max); + /* Allocate space for the allocation bitmap. */ - bitmap_size = (max+1) >> (PAGE_SHIFT+3); + bitmap_size = (max - min + 1) >> (PAGE_SHIFT+3); bitmap_size = round_pgup(bitmap_size); alloc_bitmap = (unsigned long *)to_virt(min); min += bitmap_size; range = max - min; + /* All allocated by default. */ memset(alloc_bitmap, ~0, bitmap_size); /* Free up the memory we've been given to play with. */ map_free(PHYS_PFN(min), range>>PAGE_SHIFT); + /* The buddy lists are addressed in high memory. */ min = (unsigned long) to_virt(min); max = (unsigned long) to_virt(max); + while ( range != 0 ) { /* @@ -238,7 +242,6 @@ static void init_page_allocator(unsigned long min, unsigned long max) for ( i = PAGE_SHIFT; (1UL<<(i+1)) <= range; i++ ) if ( min & (1UL<<i) ) break; - ch = (chunk_head_t *)min; min += (1UL<<i); range -= (1UL<<i); @@ -399,9 +402,7 @@ void *sbrk(ptrdiff_t increment) void init_mm(void) { - unsigned long start_pfn, max_pfn; - printk("MM: Init\n"); arch_init_mm(&start_pfn, &max_pfn); diff --git a/extras/mini-os/sched.c b/extras/mini-os/sched.c index 174945e..a1cd3a9 100644 --- a/extras/mini-os/sched.c +++ b/extras/mini-os/sched.c @@ -100,15 +100,19 @@ void schedule(void) next = NULL; MINIOS_TAILQ_FOREACH_SAFE(thread, &thread_list, thread_list, tmp) { + DEBUG("Checking thread : %s (runnable:%i)\n", thread->name, is_runnable(thread)); if (!is_runnable(thread) && thread->wakeup_time != 0LL) { - if (thread->wakeup_time <= now) + if (thread->wakeup_time <= now) { + DEBUG("Wake thread : %s\n", thread->name); wake(thread); + } else if (thread->wakeup_time < min_wakeup_time) min_wakeup_time = thread->wakeup_time; } if(is_runnable(thread)) { + DEBUG("Thread (%s) is runnable, put it next\n", thread->name); next = thread; /* Put this thread on the end of the list */ MINIOS_TAILQ_REMOVE(&thread_list, thread, thread_list); @@ -145,6 +149,9 @@ struct thread* create_thread(char *name, void (*function)(void *), void *data) unsigned long flags; /* Call architecture specific setup. */ thread = arch_create_thread(name, function, data); + if(!thread) + BUG(); //For now, FIXME should just return NULL + /* Not runable, not exited, not sleeping */ thread->flags = 0; thread->wakeup_time = 0LL; diff --git a/extras/mini-os/time.c b/extras/mini-os/time.c new file mode 100644 index 0000000..4320241 --- /dev/null +++ b/extras/mini-os/time.c @@ -0,0 +1,12 @@ +void arch_init_time(void); +void arch_fini_time(void); + +void init_time(void) +{ + arch_init_time(); +} + +void fini_time(void) +{ + arch_fini_time(); +} diff --git a/extras/mini-os/xenbus/xenbus.c b/extras/mini-os/xenbus/xenbus.c index 934f23b..8a99ee2 100644 --- a/extras/mini-os/xenbus/xenbus.c +++ b/extras/mini-os/xenbus/xenbus.c @@ -27,6 +27,7 @@ #include <mini-os/wait.h> #include <xen/io/xs_wire.h> #include <mini-os/spinlock.h> +#include <mini-os/hypervisor.h> #include <mini-os/xmalloc.h> #define min(x,y) ({ \ @@ -43,6 +44,7 @@ #endif static struct xenstore_domain_interface *xenstore_buf; +static uint32_t store_evtchn; static DECLARE_WAIT_QUEUE_HEAD(xb_waitq); DECLARE_WAIT_QUEUE_HEAD(xenbus_watch_queue); @@ -325,20 +327,23 @@ static int allocate_xenbus_id(void) return o_probe; } +void arch_init_xenbus(struct xenstore_domain_interface **xenstore_buf, uint32_t *store_evtchn); + /* Initialise xenbus. */ void init_xenbus(void) { int err; DEBUG("init_xenbus called.\n"); - xenstore_buf = mfn_to_virt(start_info.store_mfn); + + arch_init_xenbus(&xenstore_buf, &store_evtchn); + create_thread("xenstore", xenbus_thread_func, NULL); DEBUG("buf at %p.\n", xenstore_buf); - err = bind_evtchn(start_info.store_evtchn, + err = bind_evtchn(store_evtchn, xenbus_evtchn_handler, NULL); - unmask_evtchn(start_info.store_evtchn); - printk("xenbus initialised on irq %d mfn %#lx\n", - err, start_info.store_mfn); + unmask_evtchn(store_evtchn); + printk("xenbus initialised on event %d\n", err); } void fini_xenbus(void) @@ -420,7 +425,7 @@ static void xb_write(int type, int req_id, xenbus_transaction_t trans_id, xenstore_buf->req_prod += len; /* Send evtchn to notify remote */ - notify_remote_via_evtchn(start_info.store_evtchn); + notify_remote_via_evtchn(store_evtchn); } /* Send a mesasge to xenbus, in the same fashion as xb_write, and @@ -445,6 +450,7 @@ xenbus_msg_reply(int type, remove_waiter(w, req_info[id].waitq); wake(current); + rmb(); rep = req_info[id].reply; BUG_ON(rep->req_id != id); release_xenbus_id(id); -- Julien Grall _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxx http://lists.xen.org/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |