--- /dev/null
+@ Offset of the kernel within the RAM. This is a Linux/zImage convention which we
+@ rely on for now.
+#define ZIMAGE_KERNEL_OFFSET 0x8000
+
+.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 (0 = relocatable)
+ .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 arch_init() function.
+@ => r2 -> DTB
+@ <= never returns
+@ Note: this boot code needs to be within the first (1MB - ZIMAGE_KERNEL_OFFSET) of _start.
+reset:
+ @ Problem: the C code wants to be at a known address (_start), but Xen might
+ @ load us anywhere. We initialise the MMU (mapping virtual to physical @ addresses)
+ @ so everything ends up where the code expects it to be.
+ @
+ @ We calculate the offet between where the linker thought _start would be and where
+ @ it actually is and initialise the page tables to have that offset for every page.
+ @
+ @ When we turn on the MMU, we're still executing at the old address. We don't want
+ @ the code to disappear from under us. So we have to do the mapping in stages:
+ @
+ @ 1. set up a mapping to our current page from both its current and desired addresses
+ @ 2. enable the MMU
+ @ 3. jump to the new address
+ @ 4. remap all the other pages with the calculated offset
+
+ adr r1, _start @ r1 = physical address of _start
+ ldr r3, =_start @ r3 = (desired) virtual address of _start
+ sub r9, r1, r3 @ r9 = (physical - virtual) offset
+
+ ldr r7, =_page_dir @ r7 = (desired) virtual addr of translation table
+ add r1, r7, r9 @ r1 = physical addr of translation table
+
+ @ Tell the system where our page table is located.
+ @ This is the 16 KB top-level translation table, in which
+ @ each word maps one 1MB virtual section to a physical section.
+ @ Note: We leave TTBCR as 0, meaning that only TTBR0 is used and
+ @ we use the short-descriptor format (32-bit physical addresses).
+ orr r0, r1, #0b0001011 @ Sharable, Inner/Outer Write-Back Write-Allocate Cacheable
+ mcr p15, 0, r0, 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
+
+ @ Template (flags) for a 1 MB page-table entry.
+ @ TEX[2:0] C B = 001 1 1 (outer and inner write-back, write-allocate)
+ ldr r8, =(0x2 + /* Section entry */ \
+ 0xc + /* C B */ \
+ (3 << 10) + /* Read/write */ \
+ (1 << 12) + /* TEX */ \
+ (1 << 16) + /* Sharable */ \
+ (1<<19)) /* Non-secure */
+ @ r8 = template page table entry
+
+ @ Add an entry for the current physical section, at the old and new
+ @ addresses. It's OK if they're the same.
+ mov r0, pc, lsr#20
+ mov r0, r0, lsl#20 @ r0 = physical address of this code's section start
+ orr r3, r0, r8 @ r3 = table entry for this section
+ ldr r4, =_start @ r4 = desired virtual address of this section
+ str r3, [r1, r4, lsr#18] @ map desired virtual section to this code
+ str r3, [r1, r0, lsr#18] @ map current section to this code too
+
+ @ Invalidate TLB
+ dsb @ Caching is off, but must still prevent reordering
+ mcr p15, 0, r1, c8, c7, 0 @ TLBIALL
+
+ @ Enable MMU / SCTLR
+ mrc p15, 0, r1, c1, c0, 0 @ SCTLR
+ orr r1, r1, #3 << 11 @ enable icache, branch prediction
+ orr r1, r1, #4 + 1 @ enable dcache, MMU
+ mcr p15, 0, r1, c1, c0, 0 @ SCTLR
+ isb
+
+ ldr r1, =stage2 @ Virtual address of stage2
+ bx r1
+
+@ Called once the MMU is enabled. The boot code and the page table are mapped,
+@ but nothing else is yet.
+@
+@ => r2 -> dtb (physical)
+@ r7 = virtual address of page table
+@ r8 = section entry template (flags)
+@ r9 = desired physical - virtual offset
+@ pc -> somewhere in newly-mapped virtual code section
+stage2:
+ @ Invalidate TLB
+ mcr p15, 0, r1, c8, c7, 0 @ TLBIALL
+ isb
+
+ @ The new mapping has now taken effect:
+ @ r7 -> page_dir
+
+ @ Fill in the whole top-level translation table (at page_dir).
+ @ Populate the whole pagedir with 1MB section descriptors.
+
+ mov r1, r7 @ r1 -> first section entry
+ add r3, r1, #4*4*1024 @ limit (4 GB address space, 4 byte entries)
+ orr r0, r8, r9 @ r0 = entry mapping section zero to start of physical RAM
+1:
+ str r0, [r1],#4 @ write the section entry
+ add r0, r0, #1 << 20 @ next physical page (wraps)
+ cmp r1, r3
+ bne 1b
+
+ @ Invalidate TLB
+ dsb
+ mcr p15, 0, r1, c8, c7, 0 @ TLBIALL
+ isb
+
+ @ Set VBAR -> exception_vector_table
+ @ SCTLR.V = 0
+ adr r0, exception_vector_table
+ mcr p15, 0, r0, c12, c0, 0
+
+ @ Enable hardware floating point:
+ @ 1. Access to CP10 and CP11 must be enabled in the Coprocessor Access
+ @ Control Register (CP15.CACR):
+ mrc p15, 0, r1, c1, c0, 2 @ CACR
+ orr r1, r1, #(3 << 20) + (3 << 22) @ full access for CP10 & CP11
+ mcr p15, 0, r1, c1, c0, 2
+ @ 2. The EN bit in the FPEXC register must be set:
+ vmrs r0, FPEXC
+ orr r0, r0, #1<<30 @ EN (enable)
+ vmsr FPEXC, r0
+
+ @ Initialise 16 KB stack
+ ldr sp, =_boot_stack_end
+
+ sub r0, r2, r9 @ r0 -> device tree (virtual address)
+ mov r1, r9 @ r1 = physical_address_offset
+
+ b arch_init
+
+.pushsection .bss
+@ Note: calling arch_init zeroes out this region.
+.align 12
+.globl shared_info_page
+shared_info_page:
+ .fill (1024), 4, 0x0
+
+.align 3
+.globl irqstack
+.globl irqstack_end
+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
+
+@ Call fault_undefined_instruction in "Undefined mode"
+bug:
+ .word 0xe7f000f0 @ und/udf - a "Permanently Undefined" instruction
+
+irq_handler:
+ ldr sp, =irqstack_end
+ push {r0 - r12, r14}
+
+ ldr r0, IRQ_handler
+ cmp r0, #0
+ beq bug
+ blx r0 @ call handler
+
+ @ Return from IRQ
+ pop {r0 - r12, r14}
+ clrex
+ subs pc, lr, #4
+
+.globl IRQ_handler
+IRQ_handler:
+ .long 0x0
+
+@ 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
--- /dev/null
+/******************************************************************************
+ * hypercall.S
+ *
+ * Xen hypercall wrappers
+ *
+ * Stefano Stabellini <stefano.stabellini@eu.citrix.com>, Citrix, 2012
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation; or, when 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.
+ */
+
+#include <xen/xen.h>
+
+#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
+
+_hypercall2(sched_op);
+_hypercall2(memory_op);
+_hypercall2(event_channel_op);
+_hypercall2(xen_version);
+_hypercall3(console_io);
+_hypercall1(physdev_op);
+_hypercall3(grant_table_op);
+_hypercall3(vcpu_op);
+_hypercall1(sysctl);
+_hypercall1(domctl);
+_hypercall2(hvm_op);
+_hypercall1(xsm_op);
--- /dev/null
+OUTPUT_ARCH(arm)
+ENTRY(_start)
+SECTIONS
+{
+ /* Note: we currently assume that Xen will load the kernel image
+ * at start-of-RAM + 0x8000. We use this initial 32 KB for the stack
+ * and translation tables.
+ */
+ _boot_stack = 0x400000; /* 16 KB boot stack */
+ _boot_stack_end = 0x404000;
+ _page_dir = 0x404000; /* 16 KB translation table */
+ . = 0x408000;
+ _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)
+ }
+
+ /* Note: linker will insert any extra sections here, just before .bss */
+
+ .bss : {
+ _edata = .; /* End of data included in image */
+ /* Nothing after here is included in the zImage's size */
+
+ __bss_start = .;
+ *(.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) }
+}
--- /dev/null
+#include <mini-os/os.h>
+#include <mini-os/kernel.h>
+#include <mini-os/gic.h>
+#include <mini-os/console.h>
+#include <xen/xen.h>
+#include <xen/memory.h>
+#include <xen/hvm/params.h>
+#include <arch_mm.h>
+#include <libfdt.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];
+
+void *device_tree;
+
+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 %lx\n", (unsigned long) 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, uint32_t physical_offset)
+{
+ struct xen_add_to_physmap xatp;
+ int r;
+
+ memset(&__bss_start, 0, &_end - &__bss_start);
+
+ physical_address_offset = physical_offset;
+
+ xprintk("Virtual -> physical offset = %x\n", physical_address_offset);
+
+ xprintk("Checking DTB at %p...\n", dtb_pointer);
+
+ if ((r = fdt_check_header(dtb_pointer))) {
+ xprintk("Invalid DTB from Xen: %s\n", fdt_strerror(r));
+ BUG();
+ }
+ device_tree = 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();
+
+ gic_init();
+
+ start_kernel();
+}
+
+void
+arch_fini(void)
+{
+}
+
+void
+arch_do_exit(void)
+{
+}