|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [PATCH ARM v4 07/12] mini-os: initial ARM support
From: Karim Raslan <karim.allah.ahmed@xxxxxxxxx>
On ARM, Mini-OS will boot and display some output on the console.
Tested with:
make XEN_TARGET_ARCH=arm32 CROSS_COMPILE=arm-linux-gnueabihf- \
CONFIG_TEST=y CONFIG_START_NETWORK=n CONFIG_BLKFRONT=n \
CONFIG_NETFRONT=n CONFIG_FBFRONT=n CONFIG_KBDFRONT=n \
CONFIG_CONSFRONT=n CONFIG_XC=n -j4
Signed-off-by: Karim Allah Ahmed <karim.allah.ahmed@xxxxxxxxx>
[talex5@xxxxxxxxx: made x86_64 support work again]
[talex5@xxxxxxxxx: split into multiple patches]
[talex5@xxxxxxxxx: re-enabled force_evtchn_callback]
[talex5@xxxxxxxxx: enable regular console]
[talex5@xxxxxxxxx: fixed initialisation code:
- Configure write-back caching in page table. This is needed for
reliable hypercalls to Xen (thanks to Julien Grall).
- Use "client mode" for access control (domains are deprecated,
according to ARM Cortex-A Series Programmerâs Guide version 4.0,
section 9.6.4).
- Enable more SCTLR features (icache, branch prediction)]
[talex5@xxxxxxxxx: use Virtual Count register for monotonic time]
[talex5@xxxxxxxxx: fixed HYPERVISOR_shutdown]
[talex5@xxxxxxxxx: get xenstore details from hypervisor]
[talex5@xxxxxxxxx: use GCC implementation of division]
[talex5@xxxxxxxxx: include hypervisor.h from os.h, as on x86]
[talex5@xxxxxxxxx: cleaned up interrupt handlers and threading]
[talex5@xxxxxxxxx: call exit_thread when a thread returns]
[talex5@xxxxxxxxx: implemented block_domain for ARM]
[talex5@xxxxxxxxx: fixed hang when enabling interrupts]
[talex5@xxxxxxxxx: added -march=armv7-a to flags]
[talex5@xxxxxxxxx: implemented bitops for ARM]
[talex5@xxxxxxxxx: CLREX after handling IRQs]
[talex5@xxxxxxxxx: unbind debug port at shutdown]
[talex5@xxxxxxxxx: allow unaligned accesses]
[talex5@xxxxxxxxx: added arch_endian.h for ARM]
[talex5@xxxxxxxxx: fix zImage header for XSA-95]
Signed-off-by: Thomas Leonard <talex5@xxxxxxxxx>
---
extras/mini-os/ARM-TODO.txt | 12 ++
extras/mini-os/Config.mk | 2 +
extras/mini-os/Makefile | 14 ++
extras/mini-os/arch/arm/Makefile | 32 ++++
extras/mini-os/arch/arm/arch.mk | 7 +
extras/mini-os/arch/arm/arm32.S | 155 +++++++++++++++
extras/mini-os/arch/arm/events.c | 30 +++
extras/mini-os/arch/arm/hypercalls32.S | 88 +++++++++
extras/mini-os/arch/arm/minios-arm32.lds | 75 ++++++++
extras/mini-os/arch/arm/mm.c | 44 +++++
extras/mini-os/arch/arm/sched.c | 37 ++++
extras/mini-os/arch/arm/setup.c | 102 ++++++++++
extras/mini-os/arch/arm/time.c | 202 ++++++++++++++++++++
extras/mini-os/arch/x86/events.c | 4 +
extras/mini-os/drivers/gic.c | 187 ++++++++++++++++++
extras/mini-os/events.c | 5 +-
extras/mini-os/hypervisor.c | 12 +-
extras/mini-os/include/arm/arch_endian.h | 7 +
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/arm32/arch_wordsize.h | 1 +
extras/mini-os/include/arm/hypercall-arm32.h | 173 +++++++++++++++++
extras/mini-os/include/arm/os.h | 230 +++++++++++++++++++++++
extras/mini-os/include/arm/traps.h | 20 ++
extras/mini-os/include/events.h | 4 +
extras/mini-os/include/gic.h | 1 +
extras/mini-os/include/hypervisor.h | 4 +
extras/mini-os/include/mm.h | 2 +
extras/mini-os/include/types.h | 12 +-
extras/mini-os/kernel.c | 8 +
extras/mini-os/sched.c | 29 +--
33 files changed, 1595 insertions(+), 21 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/events.c
create mode 100644 extras/mini-os/arch/arm/hypercalls32.S
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/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/drivers/gic.c
create mode 100644 extras/mini-os/include/arm/arch_endian.h
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/arm32/arch_wordsize.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/include/gic.h
diff --git a/extras/mini-os/ARM-TODO.txt b/extras/mini-os/ARM-TODO.txt
new file mode 100644
index 0000000..3d9be10
--- /dev/null
+++ b/extras/mini-os/ARM-TODO.txt
@@ -0,0 +1,12 @@
+* support abort exception handling ( and others )
+* scheduling!
+* 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
+* bind_*
+* add multiple cpu support (?)
+* map_frames
+* make sure that wallclock is functioning properly
+* 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 6d6537e..535ca68 100644
--- a/extras/mini-os/Makefile
+++ b/extras/mini-os/Makefile
@@ -77,6 +77,14 @@ TARGET := mini-os
# Subdirectories common to mini-os
SUBDIRS := lib xenbus console
+ifeq ($(XEN_TARGET_ARCH),arm32)
+# ARM drivers
+src-y += drivers/gic.c
+
+# Need libgcc.a for division helpers
+LDLIBS += `$(CC) -print-libgcc-file-name`
+endif
+
src-$(CONFIG_BLKFRONT) += blkfront.c
src-$(CONFIG_TPMFRONT) += tpmfront.c
src-$(CONFIG_TPM_TIS) += tpm_tis.c
@@ -97,7 +105,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
@@ -190,7 +200,11 @@ $(OBJ_DIR)/$(TARGET): $(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..8b78651
--- /dev/null
+++ b/extras/mini-os/arch/arm/Makefile
@@ -0,0 +1,32 @@
+#
+# ARM architecture specific makefiles.
+#
+
+XEN_ROOT = $(CURDIR)/../../../..
+include $(XEN_ROOT)/Config.mk
+include ../../Config.mk
+
+# include arch.mk has to be before minios.mk!
+
+include arch.mk
+include ../../minios.mk
+
+# Sources here are all *.c (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
+
+all: $(OBJ_DIR)/$(ARCH_LIB)
+
+# $(HEAD_ARCH_OBJ) is only built 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..ab20d99
--- /dev/null
+++ b/extras/mini-os/arch/arm/arch.mk
@@ -0,0 +1,7 @@
+ifeq ($(XEN_TARGET_ARCH),arm32)
+DEF_ASFLAGS += -march=armv7-a
+ARCH_CFLAGS := -march=armv7-a -marm -fms-extensions -D__arm__
-DXEN_HAVE_PV_GUEST_ENTRY #-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..4f953ec
--- /dev/null
+++ b/extras/mini-os/arch/arm/arm32.S
@@ -0,0 +1,155 @@
+#define PHYS_START (0x80008000)
+
+.section .text
+
+.globl _start
+_start:
+ @ zImage header
+.rept 8
+ mov r0, r0
+.endr
+ b reset
+ .word 0x016f2818 @ Magic numbers to help the loader
+ .word 0 @ zImage start address
+ .word _edata - _start @ zImage end address (excludes bss section)
+ @ end of zImage header
+
+@ Called at boot time. Sets up MMU, exception vectors and stack, and then
calls C setup() function.
+@ => r2 -> DTB
+@ <= never returns
+reset:
+ @ Fill in the top-level translation table (at page_dir).
+ @ Populate the whole pagedir with 1MB section descriptors.
+ @ TEX[2:0] C B = 001 1 1 (outer and inner write-back, write-allocate)
+ ldr r0, =(0x2 + /* Section entry */ \
+ 0xc + /* C B */ \
+ (3 << 10) + /* Read/write */ \
+ (1 << 12) + /* TEX */ \
+ (1 << 16) + /* Sharable */ \
+ (1<<19)) /* Non-secure */
+ ldr r1, =page_dir
+ add r3, r1, #4*4*1024 @ Limit (4 GB address space, 4 byte
entries)
+
+1:
+ str r0, [r1],#4 @ write the section entry
+ add r0, r0, #1 << 20 @ next physical page
+ cmp r1, r3
+ bne 1b
+
+ @ Tell the system where our new table is located.
+ ldr r3, =page_dir
+ mcr p15, 0, r3, c2, c0, 0 @ set ttbr0
+
+ @ Set access permission for domains
+ @ Domains are deprecated, but we have to configure them anyway.
+ @ We mark every page as being domain 0 and set domain 0 to "client mode"
+ @ (client mode = use access flags in page table).
+ mov r0, #1 @ 1 = client
+ mcr p15, 0, r0, c3, c0, 0 @ DACR
+
+ @ Invalidate TLB
+ mcr p15, 0, r1, c8, c7, 0 @ TLBIALL
+
+ @ Enable MMU / SCTLR
+ mrc p15, 0, r1, c1, c0, 0 @ SCTLR
+ orr r1, r1, #0x5 @ (dcache, MMU)
+ orr r1, r1, #3 << 11 @ (icache, branch prediction)
+ mcr p15, 0, r1, c1, c0, 0 @ SCTLR
+ isb
+
+ @ Set VBAR -> exception_vector_table
+ @ SCTLR.V = 0
+ adr r0, exception_vector_table
+ mcr p15, 0, r0, c12, c0, 0
+
+ @ Initialise 16 KB stack
+ ldr sp, =stack_end
+
+ mov r0, r2 @ C wants the DTB pointer in r0
+ b arch_init
+
+.pushsection .data
+.align 14
+page_dir:
+ .fill (4*1024), 4, 0x0
+
+.align 12
+.globl shared_info_page
+shared_info_page:
+ .fill (1024), 4, 0x0
+
+.align 3
+.globl stack
+stack:
+ .fill (4*1024), 4, 0x0
+stack_end:
+
+.align 3
+irqstack:
+ .fill (1024), 4, 0x0
+irqstack_end:
+.popsection
+
+@ exception base address
+.align 5
+.globl exception_vector_table
+@ Note: remember to call CLREX if returning from an exception:
+@ "The architecture enables the local monitor to treat any exclusive store as
+@ matching a previous LDREX address. For this reason, use of the CLREX
+@ instruction to clear an existing tag is required on context switches."
+@ -- ARM Cortex-A Series Programmerâs Guide (Version: 4.0)
+exception_vector_table:
+ b . @ reset
+ b . @ undefined instruction
+ b . @ supervisor call
+ b . @ prefetch call
+ b . @ prefetch abort
+ b . @ data abort
+ b irq_handler @ irq
+ .word 0xe7f000f0 @ abort on FIQ
+
+irq_handler:
+ ldr sp, =irqstack_end
+ push {r0 - r12, r14}
+
+ ldr r0, IRQ_handler
+ cmp r0, #0
+ .word 0x07f000f0 @ undeq - panic if no handler
+ blx r0
+
+ @ Return from IRQ
+ pop {r0 - r12, r14}
+ clrex
+ subs pc, lr, #4
+
+.globl IRQ_handler
+IRQ_handler:
+ .long 0x0
+
+
+.globl __arch_switch_threads
+@ => r0 = prev->sp
+@ r1 = next->sp
+@ <= returns to next thread's saved return address
+__arch_switch_threads:
+ stmia r0, {sp, lr} @ Store current sp and ip to prev's struct
thread
+ str fp, [sp, #-4] @ Store fp on the old stack
+
+ ldmia r1, {sp, lr} @ Load new sp, ip from next's struct thread
+ ldr fp, [sp, #-4] @ Restore fp from the stack
+
+ mov pc, lr
+
+@ This is called if you try to divide by zero. For now, we make a supervisor
call,
+@ which will make us halt.
+.globl raise
+raise:
+ svc 0
+
+.globl arm_start_thread
+arm_start_thread:
+ pop {r0, r1}
+ @ r0 = user data
+ @ r1 -> thread's main function
+ ldr lr, =exit_thread
+ bx r1
diff --git a/extras/mini-os/arch/arm/events.c b/extras/mini-os/arch/arm/events.c
new file mode 100644
index 0000000..517e763
--- /dev/null
+++ b/extras/mini-os/arch/arm/events.c
@@ -0,0 +1,30 @@
+#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_unbind_ports(void)
+{
+ if(debug_port != -1)
+ {
+ mask_evtchn(debug_port);
+ unbind_evtchn(debug_port);
+ }
+}
+
+void arch_fini_events(void)
+{
+}
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/minios-arm32.lds
b/extras/mini-os/arch/arm/minios-arm32.lds
new file mode 100755
index 0000000..0d58395
--- /dev/null
+++ b/extras/mini-os/arch/arm/minios-arm32.lds
@@ -0,0 +1,75 @@
+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 */
+
+ /* Nothing after here is included in the zImage's size */
+
+ __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..bb6aa0e
--- /dev/null
+++ b/extras/mini-os/arch/arm/mm.c
@@ -0,0 +1,44 @@
+#include <console.h>
+#include <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/sched.c b/extras/mini-os/arch/arm/sched.c
new file mode 100644
index 0000000..1306c1b
--- /dev/null
+++ b/extras/mini-os/arch/arm/sched.c
@@ -0,0 +1,37 @@
+#include <mini-os/sched.h>
+#include <mini-os/xmalloc.h>
+
+void arm_start_thread(void);
+
+/* 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);
+
+ /* Save pointer to the thread on the stack, used by current macro */
+ *((unsigned long *)thread->stack) = (unsigned long)thread;
+
+ /* Push the details to pass to arm_start_thread onto the stack */
+ int *sp = (int *) (thread->stack + STACK_SIZE);
+ *(--sp) = (int) function;
+ *(--sp) = (int) data;
+ thread->sp = (unsigned long) sp;
+
+ thread->ip = (unsigned long) arm_start_thread;
+
+ 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..3499b37
--- /dev/null
+++ b/extras/mini-os/arch/arm/setup.c
@@ -0,0 +1,102 @@
+#include <mini-os/os.h>
+#include <mini-os/kernel.h>
+#include <xen/xen.h>
+#include <xen/memory.h>
+#include <xen/hvm/params.h>
+#include <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.
+ * On x86, the hypervisor passes it to us. On ARM, we fill it in ourselves.
+ */
+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];
+
+static 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;
+}
+
+static void get_console(void)
+{
+ uint64_t v = -1;
+
+ hvm_get_parameter(HVM_PARAM_CONSOLE_EVTCHN, &v);
+ start_info.console.domU.evtchn = v;
+
+ hvm_get_parameter(HVM_PARAM_CONSOLE_PFN, &v);
+ start_info.console.domU.mfn = v;
+
+ printk("Console is on port %d\n", start_info.console.domU.evtchn);
+ printk("Console ring is at mfn %x\n", start_info.console.domU.mfn);
+}
+
+void get_xenbus(void)
+{
+ uint64_t value;
+
+ if (hvm_get_parameter(HVM_PARAM_STORE_EVTCHN, &value))
+ BUG();
+
+ start_info.store_evtchn = (int)value;
+
+ if(hvm_get_parameter(HVM_PARAM_STORE_PFN, &value))
+ BUG();
+ start_info.store_mfn = (unsigned long)value;
+}
+
+/*
+ * 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;
+
+ /* Fill in start_info */
+ get_console();
+ get_xenbus();
+
+ 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..7c0cce5
--- /dev/null
+++ b/extras/mini-os/arch/arm/time.c
@@ -0,0 +1,202 @@
+#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
+ *************************************************************************/
+
+static uint64_t cntvct_at_init;
+static uint32_t counter_freq;
+
+/* Compute with 96 bit intermediate result: (a*b)/c */
+uint64_t muldiv64(uint64_t a, uint32_t b, uint32_t c)
+{
+ union {
+ uint64_t ll;
+ struct {
+ uint32_t low, high;
+ } l;
+ } u, res;
+ uint64_t rl, rh;
+
+ u.ll = a;
+ rl = (uint64_t)u.l.low * (uint64_t)b;
+ rh = (uint64_t)u.l.high * (uint64_t)b;
+ rh += (rl >> 32);
+ res.l.high = rh / c;
+ res.l.low = (((rh % c) << 32) + (rl & 0xffffffff)) / c;
+ return res.ll;
+}
+
+static inline s_time_t ticks_to_ns(uint64_t ticks)
+{
+ return muldiv64(ticks, SECONDS(1), counter_freq);
+}
+
+static inline uint64_t ns_to_ticks(s_time_t ns)
+{
+ return muldiv64(ns, counter_freq, SECONDS(1));
+}
+
+/* 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;
+
+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;
+}
+
+static inline uint64_t read_virtual_count(void)
+{
+ uint32_t c_lo, c_hi;
+ __asm__ __volatile__("isb;mrrc p15, 1, %0, %1, c14":"=r"(c_lo),
"=r"(c_hi));
+ return (((uint64_t) c_hi) << 32) + c_lo;
+}
+
+/* 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)
+{
+ s_time_t time = ticks_to_ns(read_virtual_count() - cntvct_at_init);
+ //printk("monotonic_clock: %llu (%llu)\n", time, NSEC_TO_SEC(time));
+ 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 set_vtimer_compare(uint64_t value) {
+ uint32_t x, y;
+
+ 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));
+}
+
+void unset_vtimer_compare(void) {
+ uint32_t x;
+
+ __asm__ __volatile__("mov %0, #0x2\n"
+ "mcr p15, 0, %0, c14, c3, 1\n" /* Disable timer and mask the
output signal */
+ "isb":"=r"(x));
+}
+
+void block_domain(s_time_t until)
+{
+ uint64_t until_count = ns_to_ticks(until) + cntvct_at_init;
+ ASSERT(irqs_disabled());
+ if (read_virtual_count() < until_count)
+ {
+ set_vtimer_compare(until_count);
+ //char buf[] = "sleep\n"; (void)HYPERVISOR_console_io(CONSOLEIO_write,
strlen(buf), buf);
+ __asm__ __volatile__("wfi");
+ //char wake[] = "wake\n"; (void)HYPERVISOR_console_io(CONSOLEIO_write,
strlen(wake), wake);
+ unset_vtimer_compare();
+
+ /* Give the IRQ handler a chance to handle whatever woke us up. */
+ local_irq_enable();
+ local_irq_disable();
+ }
+}
+
+void timer_handler(evtchn_port_t port, struct pt_regs *regs, void *ign)
+{
+ DEBUG("Timer kick\n");
+ get_time_values_from_xen();
+ update_wallclock();
+}
+
+evtchn_port_t timer_port = -1;
+
+void init_time(void)
+{
+ printk("Initialising timer interface\n");
+
+ __asm__ __volatile__("mrc p15, 0, %0, c14, c0, 0":"=r"(counter_freq));
+ cntvct_at_init = read_virtual_count();
+ printk("Virtual Count register is %llx, freq = %d Hz\n", cntvct_at_init,
counter_freq);
+
+ timer_port = bind_virq(VIRQ_TIMER, (evtchn_handler_t)timer_handler, 0);
+ if (timer_port == -1)
+ BUG();
+ unmask_evtchn(timer_port);
+}
+
+void fini_time(void)
+{
+ if (timer_port != -1)
+ {
+ mask_evtchn(timer_port);
+ unbind_evtchn(timer_port);
+ }
+}
diff --git a/extras/mini-os/arch/x86/events.c b/extras/mini-os/arch/x86/events.c
index e420a98..5198cf3 100644
--- a/extras/mini-os/arch/x86/events.c
+++ b/extras/mini-os/arch/x86/events.c
@@ -23,6 +23,10 @@ void arch_init_events(void)
#endif
}
+void arch_unbind_ports(void)
+{
+}
+
void arch_fini_events(void)
{
#if defined(__x86_64__)
diff --git a/extras/mini-os/drivers/gic.c b/extras/mini-os/drivers/gic.c
new file mode 100644
index 0000000..3141830
--- /dev/null
+++ b/extras/mini-os/drivers/gic.c
@@ -0,0 +1,187 @@
+// 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 void (*IRQ_handler)(void);
+
+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);
+}
+
+/* When accessing the GIC registers, we can't use LDREX/STREX because it's not
regular memory. */
+static __inline__ void clear_bit_non_atomic(int nr, volatile void *base)
+{
+ uint32_t *tmp = (uint32_t *)base;
+ tmp[nr >> 5] &= (unsigned long)~(1 << (nr & 0x1f));
+}
+
+static __inline__ void set_bit_non_atomic(int nr, volatile void *base)
+{
+ uint32_t *tmp = (uint32_t *)base;
+ tmp[nr >> 5] |= (1 << (nr & 0x1f));
+}
+
+/* Note: not thread safe (but we only support one CPU for now anyway) */
+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_non_atomic((irq_number * 2) + 1, cfg_reg) :
set_bit_non_atomic((irq_number * 2) + 1, cfg_reg);
+ if(ppi)
+ clear_bit_non_atomic((irq_number * 2), cfg_reg);
+
+ wmb();
+
+ // enable forwarding interrupt from distributor to cpu interface
+ set_enable_reg = (void *)gicd(gic, GICD_ISENABLER);
+ set_bit_non_atomic(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 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
+
+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);
+ 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();
+
+ IRQ_handler = gic_handler;
+
+ gic_disable_interrupts(&gic);
+ gic_cpu_set_priority(&gic, 0xff);
+
+ /* Must call gic_enable_interrupts before enabling individual interrupts,
otherwise our IRQ handler
+ * gets called endlessly with spurious interrupts. */
+ gic_enable_interrupts(&gic);
+
+ 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 */);
+}
diff --git a/extras/mini-os/events.c b/extras/mini-os/events.c
index 3c92d82..780c74a 100644
--- a/extras/mini-os/events.c
+++ b/extras/mini-os/events.c
@@ -179,6 +179,7 @@ void init_events(void)
void fini_events(void)
{
/* Dealloc all events */
+ arch_unbind_ports();
unbind_all_ports();
arch_fini_events();
}
@@ -238,7 +239,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__ /* TODO */
uint32_t sid;
struct xen_flask_op op;
op.cmd = FLASK_GET_PEER_SID;
@@ -253,6 +255,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/hypervisor.c b/extras/mini-os/hypervisor.c
index b4688a0..1b61d9b 100644
--- a/extras/mini-os/hypervisor.c
+++ b/extras/mini-os/hypervisor.c
@@ -64,7 +64,7 @@ void do_hypervisor_callback(struct pt_regs *regs)
l2 &= ~(1UL << l2i);
port = (l1i * (sizeof(unsigned long) * 8)) + l2i;
- do_event(port, regs);
+ do_event(port, regs);
}
}
@@ -73,18 +73,26 @@ void do_hypervisor_callback(struct pt_regs *regs)
void force_evtchn_callback(void)
{
+#ifdef XEN_HAVE_PV_UPCALL_MASK
int save;
+#endif
vcpu_info_t *vcpu;
vcpu = &HYPERVISOR_shared_info->vcpu_info[smp_processor_id()];
+#ifdef XEN_HAVE_PV_UPCALL_MASK
save = vcpu->evtchn_upcall_mask;
+#endif
while (vcpu->evtchn_upcall_pending) {
+#ifdef XEN_HAVE_PV_UPCALL_MASK
vcpu->evtchn_upcall_mask = 1;
+#endif
barrier();
do_hypervisor_callback(NULL);
barrier();
+#ifdef XEN_HAVE_PV_UPCALL_MASK
vcpu->evtchn_upcall_mask = save;
barrier();
+#endif
};
}
@@ -110,7 +118,9 @@ inline void unmask_evtchn(uint32_t port)
&vcpu_info->evtchn_pending_sel) )
{
vcpu_info->evtchn_upcall_pending = 1;
+#ifdef XEN_HAVE_PV_UPCALL_MASK
if ( !vcpu_info->evtchn_upcall_mask )
+#endif
force_evtchn_callback();
}
}
diff --git a/extras/mini-os/include/arm/arch_endian.h
b/extras/mini-os/include/arm/arch_endian.h
new file mode 100644
index 0000000..0771683
--- /dev/null
+++ b/extras/mini-os/include/arm/arch_endian.h
@@ -0,0 +1,7 @@
+#ifndef ARCH_ENDIAN_H
+#error "Do not include arch_endian by itself, include endian.h"
+#else
+
+#define __BYTE_ORDER __LITTLE_ENDIAN
+
+#endif
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..be14ada
--- /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) (PFN_DOWN(to_phys(_virt)))
+#define mach_to_virt(_mach) (_mach)
+#define virt_to_mach(_virt) (_virt)
+#define mfn_to_virt(_mfn) (to_virt(PFN_PHYS(_mfn)))
+#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..e2307ed
--- /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..d57f150
--- /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/arm32/arch_wordsize.h
b/extras/mini-os/include/arm/arm32/arch_wordsize.h
new file mode 100644
index 0000000..b47eee9
--- /dev/null
+++ b/extras/mini-os/include/arm/arm32/arch_wordsize.h
@@ -0,0 +1 @@
+#define __WORDSIZE 32
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..0fc1c03
--- /dev/null
+++ b/extras/mini-os/include/arm/hypercall-arm32.h
@@ -0,0 +1,173 @@
+/******************************************************************************
+ * hypercall-arm32.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 };
+ HYPERVISOR_sched_op(SCHEDOP_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..21e9276
--- /dev/null
+++ b/extras/mini-os/include/arm/os.h
@@ -0,0 +1,230 @@
+#ifndef _OS_H_
+#define _OS_H_
+
+#ifndef __ASSEMBLY__
+
+#include <mini-os/hypervisor.h>
+#include <mini-os/types.h>
+#include <xen/xen.h>
+
+void arch_fini(void);
+void timer_handler(evtchn_port_t port, struct pt_regs *regs, void *ign);
+
+#define BUG() while(1){}
+
+#define smp_processor_id() 0
+
+#define barrier() __asm__ __volatile__("": : :"memory")
+
+extern shared_info_t *HYPERVISOR_shared_info;
+
+// 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 unlikely(x) __builtin_expect((x),0)
+#define likely(x) __builtin_expect((x),1)
+
+/************************** arm *******************************/
+#ifdef __INSIDE_MINIOS__
+#if defined (__arm__)
+#define xchg(ptr,v) __atomic_exchange_n(ptr, v, __ATOMIC_SEQ_CST)
+
+/**
+ * test_and_clear_bit - Clear a bit and return its old value
+ * @nr: Bit to clear
+ * @addr: Address to count from
+ *
+ * Note that @nr may be almost arbitrarily large; this function is not
+ * restricted to acting on a single-word quantity.
+ *
+ * This operation is atomic.
+ * If you need a memory barrier, use synch_test_and_clear_bit instead.
+ */
+static __inline__ int test_and_clear_bit(int nr, volatile void * addr)
+{
+ uint8_t *byte = ((uint8_t *)addr) + (nr >> 3);
+ uint8_t bit = 1 << (nr & 7);
+ uint8_t orig;
+
+ orig = __atomic_fetch_and(byte, ~bit, __ATOMIC_RELAXED);
+
+ return (orig & bit) != 0;
+}
+
+/**
+ * Atomically set a bit and return the old value.
+ * Similar to test_and_clear_bit.
+ */
+static __inline__ int test_and_set_bit(int nr, volatile void *base)
+{
+ uint8_t *byte = ((uint8_t *)base) + (nr >> 3);
+ uint8_t bit = 1 << (nr & 7);
+ uint8_t orig;
+
+ orig = __atomic_fetch_or(byte, bit, __ATOMIC_RELAXED);
+
+ return (orig & bit) != 0;
+}
+
+/**
+ * Test whether a bit is set. */
+static __inline__ int test_bit(int nr, const volatile unsigned long *addr)
+{
+ const uint8_t *ptr = (const uint8_t *) addr;
+ return ((1 << (nr & 7)) & (ptr[nr >> 3])) != 0;
+}
+
+/**
+ * Atomically set a bit in memory (like test_and_set_bit but discards result).
+ */
+static __inline__ void set_bit(int nr, volatile unsigned long *addr)
+{
+ test_and_set_bit(nr, addr);
+}
+
+/**
+ * Atomically clear a bit in memory (like test_and_clear_bit but discards
result).
+ */
+static __inline__ void clear_bit(int nr, volatile unsigned long *addr)
+{
+ test_and_clear_bit(nr, addr);
+}
+
+/**
+ * __ffs - find first (lowest) set 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)
+{
+ int clz;
+
+ /* xxxxx10000 = word
+ * xxxxx01111 = word - 1
+ * 0000011111 = word ^ (word - 1)
+ * 4 = 31 - clz(word ^ (word - 1))
+ */
+
+ __asm__ (
+ "sub r0, %[word], #1\n"
+ "eor r0, r0, %[word]\n"
+ "clz %[clz], r0\n":
+ /* Outputs: */
+ [clz] "=r"(clz):
+ /* Inputs: */
+ [word] "r"(word):
+ /* Clobbers: */
+ "r0");
+
+ return 31 - clz;
+}
+
+#else /* ifdef __arm__ */
+#error "Unsupported architecture"
+#endif
+#endif /* ifdef __INSIDE_MINIOS */
+
+/********************* common arm32 and arm64 ****************************/
+
+/* If *ptr == old, then store new there (and return new).
+ * Otherwise, return the old value.
+ * Atomic. */
+#define synch_cmpxchg(ptr, old, new) \
+({ __typeof__(*ptr) stored = old; \
+ __atomic_compare_exchange_n(ptr, &stored, new, 0, __ATOMIC_SEQ_CST,
__ATOMIC_SEQ_CST) ? new : old; \
+})
+
+/* As test_and_clear_bit, but using __ATOMIC_SEQ_CST */
+static __inline__ int synch_test_and_clear_bit(int nr, volatile void *addr)
+{
+ uint8_t *byte = ((uint8_t *)addr) + (nr >> 3);
+ uint8_t bit = 1 << (nr & 7);
+ uint8_t orig;
+
+ orig = __atomic_fetch_and(byte, ~bit, __ATOMIC_SEQ_CST);
+
+ return (orig & bit) != 0;
+}
+
+/* As test_and_set_bit, but using __ATOMIC_SEQ_CST */
+static __inline__ int synch_test_and_set_bit(int nr, volatile void *base)
+{
+ uint8_t *byte = ((uint8_t *)base) + (nr >> 3);
+ uint8_t bit = 1 << (nr & 7);
+ uint8_t orig;
+
+ orig = __atomic_fetch_or(byte, bit, __ATOMIC_SEQ_CST);
+
+ return (orig & bit) != 0;
+}
+
+/* As set_bit, but using __ATOMIC_SEQ_CST */
+static __inline__ void synch_set_bit(int nr, volatile void *addr)
+{
+ synch_test_and_set_bit(nr, addr);
+}
+
+/* As clear_bit, but using __ATOMIC_SEQ_CST */
+static __inline__ void synch_clear_bit(int nr, volatile void *addr)
+{
+ synch_test_and_clear_bit(nr, addr);
+}
+
+/* As test_bit, but with a following memory barrier. */
+static __inline__ int synch_test_bit(int nr, volatile void *addr)
+{
+ int result;
+ result = test_bit(nr, addr);
+ barrier();
+ return result;
+}
+
+#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..704df22
--- /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/events.h b/extras/mini-os/include/events.h
index 0452d21..f571b06 100644
--- a/extras/mini-os/include/events.h
+++ b/extras/mini-os/include/events.h
@@ -26,6 +26,10 @@ typedef void (*evtchn_handler_t)(evtchn_port_t, struct
pt_regs *, void *);
/* prototypes */
void arch_init_events(void);
+
+/* Called by fini_events. Close any arch-specific ports (e.g. debug ports) */
+void arch_unbind_ports(void);
+
void arch_fini_events(void);
int do_event(evtchn_port_t port, struct pt_regs *regs);
diff --git a/extras/mini-os/include/gic.h b/extras/mini-os/include/gic.h
new file mode 100644
index 0000000..cead2e5
--- /dev/null
+++ b/extras/mini-os/include/gic.h
@@ -0,0 +1 @@
+void gic_init(void);
diff --git a/extras/mini-os/include/hypervisor.h
b/extras/mini-os/include/hypervisor.h
index a62cb78..052f4f8 100644
--- a/extras/mini-os/include/hypervisor.h
+++ b/extras/mini-os/include/hypervisor.h
@@ -18,6 +18,10 @@
#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
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 de356e8..f79ff8c 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
diff --git a/extras/mini-os/kernel.c b/extras/mini-os/kernel.c
index 9a30550..7b2b8fc 100644
--- a/extras/mini-os/kernel.c
+++ b/extras/mini-os/kernel.c
@@ -47,6 +47,10 @@
#include <xen/features.h>
#include <xen/version.h>
+#ifdef __arm__
+#include <mini-os/gic.h>
+#endif
+
uint8_t xen_features[XENFEAT_NR_SUBMAPS * 32];
void setup_xen_features(void)
@@ -147,6 +151,10 @@ void start_kernel(void)
create_thread("shutdown", shutdown_thread, NULL);
#endif
+#ifdef __arm__
+ gic_init();
+#endif
+
/* Call (possibly overridden) app_main() */
app_main(&start_info);
diff --git a/extras/mini-os/sched.c b/extras/mini-os/sched.c
index 174945e..b99d7dc 100644
--- a/extras/mini-os/sched.c
+++ b/extras/mini-os/sched.c
@@ -145,6 +145,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;
@@ -165,28 +168,28 @@ struct _reent *__getreent(void)
struct _reent *_reent;
if (!threads_started)
- _reent = _impure_ptr;
+ _reent = _impure_ptr;
else if (in_callback)
- _reent = &callback_reent;
+ _reent = &callback_reent;
else
- _reent = &get_current()->reent;
+ _reent = &get_current()->reent;
#ifndef NDEBUG
#if defined(__x86_64__) || defined(__x86__)
{
#ifdef __x86_64__
- register unsigned long sp asm ("rsp");
+ register unsigned long sp asm ("rsp");
#else
- register unsigned long sp asm ("esp");
+ register unsigned long sp asm ("esp");
#endif
- if ((sp & (STACK_SIZE-1)) < STACK_SIZE / 16) {
- static int overflowing;
- if (!overflowing) {
- overflowing = 1;
- printk("stack overflow\n");
- BUG();
- }
- }
+ if ((sp & (STACK_SIZE-1)) < STACK_SIZE / 16) {
+ static int overflowing;
+ if (!overflowing) {
+ overflowing = 1;
+ printk("stack overflow\n");
+ BUG();
+ }
+ }
}
#endif
#else
--
2.0.0
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |