Mailing List Archive

[PATCH RFC 12/25] arm: entry.S and head.S
From: Stefano Stabellini <stefano.stabellini@eu.citrix.com>

Low level assembly routines, including entry.S and head.S.
Also the linker script and a collection of dummy functions that we plan
to reduce to zero as soon as possible.

Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
Signed-off-by: Ian Campbell <ian.campbell@citrix.com>
Signed-off-by: Tim Deegan <Tim.Deegan@citrix.com>
---
xen/arch/arm/Makefile | 5 +-
xen/arch/arm/asm-offsets.c | 76 ++++++++++
xen/arch/arm/dummy.S | 72 ++++++++++
xen/arch/arm/entry.S | 107 ++++++++++++++
xen/arch/arm/head.S | 298 +++++++++++++++++++++++++++++++++++++++
xen/arch/arm/xen.lds.S | 141 ++++++++++++++++++
xen/include/asm-arm/asm_defns.h | 18 +++
7 files changed, 716 insertions(+), 1 deletions(-)
create mode 100644 xen/arch/arm/asm-offsets.c
create mode 100644 xen/arch/arm/dummy.S
create mode 100644 xen/arch/arm/entry.S
create mode 100644 xen/arch/arm/head.S
create mode 100644 xen/arch/arm/xen.lds.S
create mode 100644 xen/include/asm-arm/asm_defns.h

diff --git a/xen/arch/arm/Makefile b/xen/arch/arm/Makefile
index fd86cb0..6a250f1 100644
--- a/xen/arch/arm/Makefile
+++ b/xen/arch/arm/Makefile
@@ -1,8 +1,11 @@
subdir-y += lib

+obj-y += dummy.o
+obj-y += entry.o
+
#obj-bin-y += ....o

-ALL_OBJS := $(ALL_OBJS)
+ALL_OBJS := head.o $(ALL_OBJS)

$(TARGET): $(TARGET)-syms
# XXX: VE model loads by VMA so instead of
diff --git a/xen/arch/arm/asm-offsets.c b/xen/arch/arm/asm-offsets.c
new file mode 100644
index 0000000..ee5d5d4
--- /dev/null
+++ b/xen/arch/arm/asm-offsets.c
@@ -0,0 +1,76 @@
+/*
+ * Generate definitions needed by assembly language modules.
+ * This code generates raw asm output which is post-processed
+ * to extract and format the required data.
+ */
+#define COMPILE_OFFSETS
+
+#include <xen/config.h>
+#include <xen/types.h>
+#include <public/xen.h>
+#include <asm/current.h>
+
+#define DEFINE(_sym, _val) \
+ __asm__ __volatile__ ( "\n->" #_sym " %0 " #_val : : "i" (_val) )
+#define BLANK() \
+ __asm__ __volatile__ ( "\n->" : : )
+#define OFFSET(_sym, _str, _mem) \
+ DEFINE(_sym, offsetof(_str, _mem));
+
+/* base-2 logarithm */
+#define __L2(_x) (((_x) & 0x00000002) ? 1 : 0)
+#define __L4(_x) (((_x) & 0x0000000c) ? ( 2 + __L2( (_x)>> 2)) : __L2( _x))
+#define __L8(_x) (((_x) & 0x000000f0) ? ( 4 + __L4( (_x)>> 4)) : __L4( _x))
+#define __L16(_x) (((_x) & 0x0000ff00) ? ( 8 + __L8( (_x)>> 8)) : __L8( _x))
+#define LOG_2(_x) (((_x) & 0xffff0000) ? (16 + __L16((_x)>>16)) : __L16(_x))
+
+void __dummy__(void)
+{
+ OFFSET(UREGS_sp, struct cpu_user_regs, sp);
+ OFFSET(UREGS_lr, struct cpu_user_regs, lr);
+ OFFSET(UREGS_pc, struct cpu_user_regs, pc);
+ OFFSET(UREGS_cpsr, struct cpu_user_regs, cpsr);
+
+ OFFSET(UREGS_LR_usr, struct cpu_user_regs, lr_usr);
+ OFFSET(UREGS_SP_usr, struct cpu_user_regs, sp_usr);
+
+ OFFSET(UREGS_SP_svc, struct cpu_user_regs, sp_svc);
+ OFFSET(UREGS_LR_svc, struct cpu_user_regs, lr_svc);
+ OFFSET(UREGS_SPSR_svc, struct cpu_user_regs, spsr_svc);
+
+ OFFSET(UREGS_SP_abt, struct cpu_user_regs, sp_abt);
+ OFFSET(UREGS_LR_abt, struct cpu_user_regs, lr_abt);
+ OFFSET(UREGS_SPSR_abt, struct cpu_user_regs, spsr_abt);
+
+ OFFSET(UREGS_SP_und, struct cpu_user_regs, sp_und);
+ OFFSET(UREGS_LR_und, struct cpu_user_regs, lr_und);
+ OFFSET(UREGS_SPSR_und, struct cpu_user_regs, spsr_und);
+
+ OFFSET(UREGS_SP_irq, struct cpu_user_regs, sp_irq);
+ OFFSET(UREGS_LR_irq, struct cpu_user_regs, lr_irq);
+ OFFSET(UREGS_SPSR_irq, struct cpu_user_regs, spsr_irq);
+
+ OFFSET(UREGS_SP_fiq, struct cpu_user_regs, sp_fiq);
+ OFFSET(UREGS_LR_fiq, struct cpu_user_regs, lr_fiq);
+ OFFSET(UREGS_SPSR_fiq, struct cpu_user_regs, spsr_fiq);
+
+ OFFSET(UREGS_R8_fiq, struct cpu_user_regs, r8_fiq);
+ OFFSET(UREGS_R9_fiq, struct cpu_user_regs, r9_fiq);
+ OFFSET(UREGS_R10_fiq, struct cpu_user_regs, r10_fiq);
+ OFFSET(UREGS_R11_fiq, struct cpu_user_regs, r11_fiq);
+ OFFSET(UREGS_R12_fiq, struct cpu_user_regs, r12_fiq);
+
+ OFFSET(UREGS_kernel_sizeof, struct cpu_user_regs, cpsr);
+ DEFINE(UREGS_user_sizeof, sizeof(struct cpu_user_regs));
+ BLANK();
+
+ DEFINE(CPUINFO_sizeof, sizeof(struct cpu_info));
+}
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "BSD"
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/xen/arch/arm/dummy.S b/xen/arch/arm/dummy.S
new file mode 100644
index 0000000..5bc4f21
--- /dev/null
+++ b/xen/arch/arm/dummy.S
@@ -0,0 +1,72 @@
+/* Nothing is mapped at 1G, for the moment */
+#define DUMMY(x) \
+ .globl x; \
+x: .word 0xe7f000f0
+/* x: mov r0, #0x40000000 ; str r0, [r0]; b x */
+
+#define NOP(x) \
+ .globl x; \
+x: mov pc, lr
+
+DUMMY(alloc_pirq_struct);
+DUMMY(alloc_vcpu_guest_context);
+DUMMY(arch_do_domctl);
+DUMMY(arch_do_sysctl);
+DUMMY(arch_do_vcpu_op);
+DUMMY(arch_get_info_guest);
+DUMMY(arch_get_xen_caps);
+DUMMY(arch_memory_op);
+DUMMY(arch_set_info_guest);
+DUMMY(arch_vcpu_reset);
+DUMMY(create_grant_host_mapping);
+DUMMY(__cpu_die);
+DUMMY(__cpu_disable);
+DUMMY(__cpu_up);
+DUMMY(do_get_pm_info);
+DUMMY(domain_get_maximum_gpfn);
+DUMMY(domain_relinquish_resources);
+DUMMY(domain_set_time_offset);
+DUMMY(dom_cow);
+DUMMY(donate_page);
+DUMMY(do_pm_op);
+DUMMY(flush_tlb_mask);
+DUMMY(free_vcpu_guest_context);
+DUMMY(get_page);
+DUMMY(get_page_type);
+DUMMY(gmfn_to_mfn);
+DUMMY(gnttab_clear_flag);
+DUMMY(gnttab_host_mapping_get_page_type);
+DUMMY(gnttab_mark_dirty);
+DUMMY(hypercall_create_continuation);
+DUMMY(iommu_map_page);
+DUMMY(iommu_unmap_page);
+DUMMY(is_iomem_page);
+DUMMY(local_event_delivery_enable);
+DUMMY(local_events_need_delivery);
+DUMMY(machine_to_phys_mapping_valid);
+DUMMY(max_page);
+DUMMY(node_online_map);
+DUMMY(nr_irqs_gsi);
+DUMMY(p2m_pod_decrease_reservation);
+DUMMY(guest_physmap_mark_populate_on_demand);
+DUMMY(page_get_owner_and_reference);
+DUMMY(page_is_ram_type);
+DUMMY(per_cpu__cpu_core_mask);
+DUMMY(per_cpu__cpu_sibling_mask);
+DUMMY(__per_cpu_offset);
+DUMMY(pirq_guest_bind);
+DUMMY(pirq_guest_unbind);
+DUMMY(pirq_set_affinity);
+DUMMY(put_page);
+DUMMY(put_page_type);
+DUMMY(replace_grant_host_mapping);
+DUMMY(send_timer_event);
+DUMMY(share_xen_page_with_privileged_guests);
+DUMMY(smp_send_state_dump);
+DUMMY(steal_page);
+DUMMY(sync_vcpu_execstate);
+DUMMY(__udelay);
+NOP(update_vcpu_system_time);
+DUMMY(vcpu_mark_events_pending);
+DUMMY(vcpu_show_execution_state);
+DUMMY(wallclock_time);
diff --git a/xen/arch/arm/entry.S b/xen/arch/arm/entry.S
new file mode 100644
index 0000000..16a8f36
--- /dev/null
+++ b/xen/arch/arm/entry.S
@@ -0,0 +1,107 @@
+#include <xen/config.h>
+#include <asm/asm_defns.h>
+
+#define SAVE_ONE_BANKED(reg) mrs r11, reg; str r11, [sp, #UREGS_##reg]
+#define RESTORE_ONE_BANKED(reg) ldr r11, [sp, #UREGS_##reg]; msr reg, r11
+
+#define SAVE_BANKED(mode) \
+ SAVE_ONE_BANKED(SP_##mode) ; SAVE_ONE_BANKED(LR_##mode) ; SAVE_ONE_BANKED(SPSR_##mode)
+
+#define RESTORE_BANKED(mode) \
+ RESTORE_ONE_BANKED(SP_##mode) ; RESTORE_ONE_BANKED(LR_##mode) ; RESTORE_ONE_BANKED(SPSR_##mode)
+
+#define SAVE_ALL \
+ sub sp, #(UREGS_R8_fiq - UREGS_sp); /* SP, LR, SPSR, PC */ \
+ push {r0-r12}; /* Save R0-R12 */ \
+ \
+ mrs r11, ELR_hyp; /* ELR_hyp is return address. */ \
+ str r11, [sp, #UREGS_pc]; \
+ \
+ str lr, [sp, #UREGS_lr]; \
+ \
+ add r11, sp, #UREGS_kernel_sizeof+4; \
+ str r11, [sp, #UREGS_sp]; \
+ \
+ mrs r11, SPSR_hyp; \
+ str r11, [sp, #UREGS_cpsr]; \
+ and r11, #PSR_MODE_MASK; \
+ cmp r11, #PSR_MODE_HYP; \
+ blne save_guest_regs
+
+save_guest_regs:
+ ldr r11, [sp, #UREGS_lr]
+ str r11, [sp, #UREGS_LR_usr]
+ ldr r11, =0xffffffff /* Clobber SP which is only valid for hypervisor frames. */
+ str r11, [sp, #UREGS_sp]
+ SAVE_ONE_BANKED(SP_usr)
+ SAVE_BANKED(svc)
+ SAVE_BANKED(abt)
+ SAVE_BANKED(und)
+ SAVE_BANKED(irq)
+ SAVE_BANKED(fiq)
+ SAVE_ONE_BANKED(R8_fiq); SAVE_ONE_BANKED(R9_fiq); SAVE_ONE_BANKED(R10_fiq)
+ SAVE_ONE_BANKED(R11_fiq); SAVE_ONE_BANKED(R12_fiq);
+ mov pc, lr
+
+#define DEFINE_TRAP_ENTRY(trap) \
+ ALIGN; \
+trap_##trap: \
+ SAVE_ALL; \
+ adr lr, return_from_trap; \
+ mov r0, sp; \
+ mov r11, sp; \
+ bic sp, #7; /* Align the stack pointer (noop on guest trap) */ \
+ b do_trap_##trap
+
+.globl hyp_traps_vector
+ .align 5
+hyp_traps_vector:
+ .word 0 /* 0x00 - Reset */
+ b trap_undefined_instruction /* 0x04 - Undefined Instruction */
+ b trap_supervisor_call /* 0x08 - Supervisor Call */
+ b trap_prefetch_abort /* 0x0c - Prefetch Abort */
+ b trap_data_abort /* 0x10 - Data Abort */
+ b trap_hypervisor /* 0x14 - Hypervisor */
+ b trap_irq /* 0x18 - IRQ */
+ b trap_fiq /* 0x1c - FIQ */
+
+DEFINE_TRAP_ENTRY(undefined_instruction)
+DEFINE_TRAP_ENTRY(supervisor_call)
+DEFINE_TRAP_ENTRY(prefetch_abort)
+DEFINE_TRAP_ENTRY(data_abort)
+DEFINE_TRAP_ENTRY(hypervisor)
+DEFINE_TRAP_ENTRY(irq)
+DEFINE_TRAP_ENTRY(fiq)
+
+ENTRY(return_from_trap)
+ ldr r11, [sp, #UREGS_cpsr]
+ and r11, #PSR_MODE_MASK
+ cmp r11, #PSR_MODE_HYP
+ beq return_to_hypervisor
+
+ENTRY(return_to_guest)
+ mov r11, sp
+ bic sp, #7 /* Align the stack pointer */
+ bl leave_hypervisor_tail
+ ldr r11, [sp, #UREGS_pc]
+ msr ELR_hyp, r11
+ ldr r11, [sp, #UREGS_cpsr]
+ msr SPSR_hyp, r11
+ RESTORE_ONE_BANKED(SP_usr)
+ RESTORE_BANKED(svc)
+ RESTORE_BANKED(abt)
+ RESTORE_BANKED(und)
+ RESTORE_BANKED(irq)
+ RESTORE_BANKED(fiq)
+ RESTORE_ONE_BANKED(R8_fiq); RESTORE_ONE_BANKED(R9_fiq); RESTORE_ONE_BANKED(R10_fiq)
+ RESTORE_ONE_BANKED(R11_fiq); RESTORE_ONE_BANKED(R12_fiq);
+ ldr lr, [sp, #UREGS_LR_usr]
+ pop {r0-r12}
+ add sp, #(UREGS_R8_fiq - UREGS_sp); /* SP, LR, SPSR, PC */
+ eret
+
+ENTRY(return_to_hypervisor)
+ ldr lr, [sp, #UREGS_lr]
+ pop {r0-r12}
+ add sp, #(UREGS_R8_fiq - UREGS_sp); /* SP, LR, SPSR, PC */
+ eret
diff --git a/xen/arch/arm/head.S b/xen/arch/arm/head.S
new file mode 100644
index 0000000..b98c921
--- /dev/null
+++ b/xen/arch/arm/head.S
@@ -0,0 +1,298 @@
+/*
+ * xen/arch/arm/head.S
+ *
+ * Start-of-day code for an ARMv7-A with virt extensions.
+ *
+ * Tim Deegan <tim@xen.org>
+ * Copyright (c) 2011 Citrix Systems.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <asm/config.h>
+#include <asm/page.h>
+#include <asm/asm_defns.h>
+
+
+/* Macro to print a string to the UART, if there is one.
+ * Clobbers r0-r3. */
+#ifdef EARLY_UART_ADDRESS
+#define PRINT(_s) \
+ adr r0, 98f ; \
+ bl puts ; \
+ b 99f ; \
+98: .asciz _s ; \
+ .align 2 ; \
+99:
+#else
+#define PRINT(s)
+#endif
+
+ .arm
+
+ /* This must be the very first address in the loaded image.
+ * It should be linked at XEN_VIRT_START, and loaded at any
+ * 2MB-aligned address. All of text+data+bss must fit in 2MB,
+ * or the initial pagetable code below will need adjustment. */
+ .global start
+start:
+ cpsid aif /* Disable all interrupts */
+
+ /* Save the bootloader arguments in less-clobberable registers */
+ mov r7, r1 /* r7 := ARM-linux machine type */
+ mov r8, r2 /* r8 := ATAG base address */
+
+ /* Find out where we are */
+ ldr r0, =start
+ adr r9, start /* r9 := paddr (start) */
+ sub r10, r9, r0 /* r10 := phys-offset */
+
+#ifdef EARLY_UART_ADDRESS
+ /* Say hello */
+ ldr r11, =EARLY_UART_ADDRESS /* r11 := UART base address */
+ bl init_uart
+#endif
+
+ /* Check that this CPU has Hyp mode */
+ mrc CP32(r0, ID_PFR1)
+ and r0, r0, #0xf000 /* Bits 12-15 define virt extensions */
+ teq r0, #0x1000 /* Must == 0x1 or may be incompatible */
+ beq 1f
+ bl putn
+ PRINT("- CPU doesn't support the virtualization extensions -\r\n")
+ b fail
+1:
+ /* Check if we're already in it */
+ mrs r0, cpsr
+ and r0, r0, #0x1f /* Mode is in the low 5 bits of CPSR */
+ teq r0, #0x1a /* Hyp Mode? */
+ bne 1f
+ PRINT("- Started in Hyp mode -\r\n")
+ b hyp
+1:
+ /* Otherwise, it must have been Secure Supervisor mode */
+ mrc CP32(r0, SCR)
+ tst r0, #0x1 /* Not-Secure bit set? */
+ beq 1f
+ PRINT("- CPU is not in Hyp mode or Secure state -\r\n")
+ b fail
+1:
+ /* OK, we're in Secure state. */
+ PRINT("- Started in Secure state -\r\n- Entering Hyp mode -\r\n")
+
+ /* Dance into Hyp mode */
+ cpsid aif, #0x16 /* Enter Monitor mode */
+ mrc CP32(r0, SCR)
+ orr r0, r0, #0x100 /* Set HCE */
+ orr r0, r0, #0xb1 /* Set SCD, AW, FW and NS */
+ bic r0, r0, #0xe /* Clear EA, FIQ and IRQ */
+ mcr CP32(r0, SCR)
+ /* Ugly: the system timer's frequency register is only
+ * programmable in Secure state. Since we don't know where its
+ * memory-mapped control registers live, we can't find out the
+ * right frequency. Use the VE model's default frequency here. */
+ ldr r0, =0x5f5e100 /* 100 MHz */
+ mcr CP32(r0, CNTFRQ)
+ ldr r0, =0x40c00 /* SMP, c11, c10 in non-secure mode */
+ mcr CP32(r0, NSACR)
+ /* Continuing ugliness: Set up the GIC so NS state owns interrupts */
+ mov r0, #GIC_BASE_ADDRESS
+ add r0, r0, #GIC_DR_OFFSET
+ mov r1, #0
+ str r1, [r0] /* Disable delivery in the distributor */
+ add r0, r0, #0x80 /* GICD_IGROUP0 */
+ mov r2, #0xffffffff /* All interrupts to group 1 */
+ str r2, [r0]
+ str r2, [r0, #4]
+ str r2, [r0, #8]
+ /* Must drop priority mask below 0x80 before entering NS state */
+ mov r0, #GIC_BASE_ADDRESS
+ add r0, r0, #GIC_CR_OFFSET
+ ldr r1, =0xff
+ str r1, [r0, #0x4] /* -> GICC_PMR */
+ /* Reset a few config registers */
+ mov r0, #0
+ mcr CP32(r0, FCSEIDR)
+ mcr CP32(r0, CONTEXTIDR)
+ /* FIXME: ought to reset some other NS control regs here */
+ adr r1, 1f
+ adr r0, hyp /* Store paddr (hyp entry point) */
+ str r0, [r1] /* where we can use it for RFE */
+ isb /* Ensure we see the stored target address */
+ rfeia r1 /* Enter Hyp mode */
+
+1: .word 0 /* PC to enter Hyp mode at */
+ .word 0x000001da /* CPSR: LE, Abort/IRQ/FIQ off, Hyp */
+
+hyp:
+ PRINT("- Setting up control registers -\r\n")
+
+ /* Set up memory attribute type tables */
+ ldr r0, =MAIR0VAL
+ ldr r1, =MAIR1VAL
+ mcr CP32(r0, MAIR0)
+ mcr CP32(r1, MAIR1)
+ mcr CP32(r0, HMAIR0)
+ mcr CP32(r1, HMAIR1)
+
+ /* Set up the HTCR:
+ * PT walks use Outer-Shareable accesses,
+ * PT walks are write-back, no-write-allocate in both cache levels,
+ * Full 32-bit address space goes through this table. */
+ ldr r0, =0x80002500
+ mcr CP32(r0, HTCR)
+
+ /* Set up the HSCTLR:
+ * Exceptions in LE ARM,
+ * Low-latency IRQs disabled,
+ * Write-implies-XN disabled (for now),
+ * I-cache and d-cache enabled,
+ * Alignment checking enabled,
+ * MMU translation disabled (for now). */
+ ldr r0, =(HSCTLR_BASE|SCTLR_A|SCTLR_C)
+ mcr CP32(r0, HSCTLR)
+
+ /* Write Xen's PT's paddr into the HTTBR */
+ ldr r4, =xen_pgtable
+ add r4, r4, r10 /* r4 := paddr (xen_pagetable) */
+ mov r5, #0 /* r4:r5 is paddr (xen_pagetable) */
+ mcrr CP64(r4, r5, HTTBR)
+
+ /* Build the baseline idle pagetable's first-level entries */
+ ldr r1, =xen_second
+ add r1, r1, r10 /* r1 := paddr (xen_second) */
+ mov r3, #0x0
+ orr r2, r1, #0xe00 /* r2:r3 := table map of xen_second */
+ orr r2, r2, #0x07f /* (+ rights for linear PT) */
+ strd r2, r3, [r4, #0] /* Map it in slot 0 */
+ add r2, r2, #0x1000
+ strd r2, r3, [r4, #8] /* Map 2nd page in slot 1 */
+ add r2, r2, #0x1000
+ strd r2, r3, [r4, #16] /* Map 3rd page in slot 2 */
+ add r2, r2, #0x1000
+ strd r2, r3, [r4, #24] /* Map 4th page in slot 3 */
+
+ /* Now set up the second-level entries */
+ orr r2, r9, #0xe00
+ orr r2, r2, #0x07d /* r2:r3 := 2MB normal map of Xen */
+ mov r4, r9, lsr #18 /* Slot for paddr(start) */
+ strd r2, r3, [r1, r4] /* Map Xen there */
+ ldr r4, =start
+ lsr r4, #18 /* Slot for vaddr(start) */
+ strd r2, r3, [r1, r4] /* Map Xen there too */
+#ifdef EARLY_UART_ADDRESS
+ ldr r3, =(1<<(54-32)) /* NS for device mapping */
+ lsr r2, r11, #21
+ lsl r2, r2, #21 /* 2MB-aligned paddr of UART */
+ orr r2, r2, #0xe00
+ orr r2, r2, #0x071 /* r2:r3 := 2MB dev map including UART */
+ add r4, r4, #8
+ strd r2, r3, [r1, r4] /* Map it in the fixmap's slot */
+#endif
+
+ PRINT("- Turning on paging -\r\n")
+
+ ldr r1, =paging /* Explicit vaddr, not RIP-relative */
+ mrc CP32(r0, HSCTLR)
+ orr r0, r0, #0x1 /* Add in the MMU enable bit */
+ dsb /* Flush PTE writes and finish reads */
+ mcr CP32(r0, HSCTLR) /* now paging is enabled */
+ isb /* Now, flush the icache */
+ mov pc, r1 /* Get a proper vaddr into PC */
+paging:
+
+#ifdef EARLY_UART_ADDRESS
+ /* Recover the UART address in the new address space */
+ lsl r11, #11
+ lsr r11, #11 /* UART base's offset from 2MB base */
+ adr r0, start
+ add r0, r0, #0x200000 /* vaddr of the fixmap's 2MB slot */
+ add r11, r11, r0 /* r11 := vaddr (UART base address) */
+#endif
+
+ PRINT("- Entering C -\r\n")
+
+ ldr sp, =init_stack /* Supply a stack */
+ add sp, #STACK_SIZE /* (which grows down from the top). */
+ sub sp, #CPUINFO_sizeof /* Make room for CPU save record */
+ mov r0, r10 /* Marshal args: - phys_offset */
+ mov r1, r7 /* - machine type */
+ mov r2, r8 /* - ATAG address */
+ b start_xen /* and disappear into the land of C */
+
+/* Fail-stop
+ * r0: string explaining why */
+fail: PRINT("- Boot failed -\r\n")
+1: wfe
+ b 1b
+
+#ifdef EARLY_UART_ADDRESS
+
+/* Bring up the UART. Specific to the PL011 UART.
+ * Clobbers r0-r2 */
+init_uart:
+ mov r1, #0x0
+ str r1, [r11, #0x24] /* -> UARTIBRD (Baud divisor fraction) */
+ mov r1, #0x4 /* 7.3728MHz / 0x4 == 16 * 115200 */
+ str r1, [r11, #0x24] /* -> UARTIBRD (Baud divisor integer) */
+ mov r1, #0x60 /* 8n1 */
+ str r1, [r11, #0x24] /* -> UARTLCR_H (Line control) */
+ ldr r1, =0x00000301 /* RXE | TXE | UARTEN */
+ str r1, [r11, #0x30] /* -> UARTCR (Control Register) */
+ adr r0, 1f
+ b puts
+1: .asciz "- UART enabled -\r\n"
+ .align 4
+
+/* Print early debug messages. Specific to the PL011 UART.
+ * r0: Nul-terminated string to print.
+ * Clobbers r0-r2 */
+puts:
+ ldr r2, [r11, #0x18] /* <- UARTFR (Flag register) */
+ tst r2, #0x8 /* Check BUSY bit */
+ bne puts /* Wait for the UART to be ready */
+ ldrb r2, [r0], #1 /* Load next char */
+ teq r2, #0 /* Exit on nul*/
+ moveq pc, lr
+ str r2, [r11] /* -> UARTDR (Data Register) */
+ b puts
+
+/* Print a 32-bit number in hex. Specific to the PL011 UART.
+ * r0: Number to print.
+ * clobbers r0-r3 */
+putn:
+ adr r1, hex
+ mov r3, #8
+1: ldr r2, [r11, #0x18] /* <- UARTFR (Flag register) */
+ tst r2, #0x8 /* Check BUSY bit */
+ bne 1b /* Wait for the UART to be ready */
+ and r2, r0, #0xf0000000 /* Mask off the top nybble */
+ ldrb r2, [r1, r2, lsr #28] /* Convert to a char */
+ str r2, [r11] /* -> UARTDR (Data Register) */
+ lsl r0, #4 /* Roll it through one nybble at a time */
+ subs r3, r3, #1
+ bne 1b
+ adr r0, crlf /* Finish with a newline */
+ b puts
+
+crlf: .asciz "\r\n"
+hex: .ascii "0123456789abcdef"
+ .align 2
+
+#else /* EARLY_UART_ADDRESS */
+
+init_uart:
+.global early_puts
+early_puts:
+puts:
+putn: mov pc, lr
+
+#endif /* EARLY_UART_ADDRESS */
diff --git a/xen/arch/arm/xen.lds.S b/xen/arch/arm/xen.lds.S
new file mode 100644
index 0000000..5a62e2c
--- /dev/null
+++ b/xen/arch/arm/xen.lds.S
@@ -0,0 +1,141 @@
+/* Excerpts written by Martin Mares <mj@atrey.karlin.mff.cuni.cz> */
+/* Modified for i386/x86-64 Xen by Keir Fraser */
+/* Modified for ARM Xen by Ian Campbell */
+
+#include <xen/config.h>
+#include <xen/cache.h>
+#include <asm/page.h>
+#include <asm/percpu.h>
+#undef ENTRY
+#undef ALIGN
+
+ENTRY(start)
+
+OUTPUT_ARCH(arm)
+
+PHDRS
+{
+ text PT_LOAD /* XXX should be AT ( XEN_PHYS_START ) */ ;
+}
+SECTIONS
+{
+ . = XEN_VIRT_START;
+ _start = .;
+ .text : /* XXX should be AT ( XEN_PHYS_START ) */ {
+ _stext = .; /* Text section */
+ *(.text)
+ *(.fixup)
+ *(.gnu.warning)
+ _etext = .; /* End of text section */
+ } :text = 0x9090
+
+ . = ALIGN(PAGE_SIZE);
+ .rodata : {
+ _srodata = .; /* Read-only data */
+ *(.rodata)
+ *(.rodata.*)
+ _erodata = .; /* End of read-only data */
+ } :text
+
+ .data : { /* Data */
+ . = ALIGN(PAGE_SIZE);
+ *(.data.page_aligned)
+ *(.data)
+ *(.data.rel)
+ *(.data.rel.*)
+ CONSTRUCTORS
+ } :text
+
+ . = ALIGN(SMP_CACHE_BYTES);
+ .data.read_mostly : {
+ /* Exception table */
+ __start___ex_table = .;
+ *(.ex_table)
+ __stop___ex_table = .;
+
+ /* Pre-exception table */
+ __start___pre_ex_table = .;
+ *(.ex_table.pre)
+ __stop___pre_ex_table = .;
+
+ *(.data.read_mostly)
+ *(.data.rel.ro)
+ *(.data.rel.ro.*)
+ } :text
+
+#ifdef LOCK_PROFILE
+ . = ALIGN(32);
+ __lock_profile_start = .;
+ .lockprofile.data : { *(.lockprofile.data) } :text
+ __lock_profile_end = .;
+#endif
+
+ . = ALIGN(PAGE_SIZE); /* Init code and data */
+ __init_begin = .;
+ .init.text : {
+ _sinittext = .;
+ *(.init.text)
+ _einittext = .;
+ } :text
+ . = ALIGN(PAGE_SIZE);
+ .init.data : {
+ *(.init.rodata)
+ *(.init.rodata.str*)
+ *(.init.data)
+ *(.init.data.rel)
+ *(.init.data.rel.*)
+ } :text
+ . = ALIGN(32);
+ .init.setup : {
+ __setup_start = .;
+ *(.init.setup)
+ __setup_end = .;
+ } :text
+ .initcall.init : {
+ __initcall_start = .;
+ *(.initcallpresmp.init)
+ __presmp_initcall_end = .;
+ *(.initcall1.init)
+ __initcall_end = .;
+ } :text
+ .xsm_initcall.init : {
+ __xsm_initcall_start = .;
+ *(.xsm_initcall.init)
+ __xsm_initcall_end = .;
+ } :text
+ . = ALIGN(STACK_SIZE);
+ __init_end = .;
+
+ .bss : { /* BSS */
+ __bss_start = .;
+ *(.bss.stack_aligned)
+ . = ALIGN(PAGE_SIZE);
+ *(.bss.page_aligned)
+ *(.bss)
+ . = ALIGN(SMP_CACHE_BYTES);
+ __per_cpu_start = .;
+ *(.bss.percpu)
+ . = ALIGN(SMP_CACHE_BYTES);
+ *(.bss.percpu.read_mostly)
+ . = ALIGN(SMP_CACHE_BYTES);
+ __per_cpu_data_end = .;
+ } :text
+ _end = . ;
+
+ /* Sections to be discarded */
+ /DISCARD/ : {
+ *(.exit.text)
+ *(.exit.data)
+ *(.exitcall.exit)
+ *(.eh_frame)
+ }
+
+ /* 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/xen/include/asm-arm/asm_defns.h b/xen/include/asm-arm/asm_defns.h
new file mode 100644
index 0000000..c59fb6c
--- /dev/null
+++ b/xen/include/asm-arm/asm_defns.h
@@ -0,0 +1,18 @@
+#ifndef __ARM_ASM_DEFNS_H__
+#define __ARM_ASM_DEFNS_H__
+
+#ifndef COMPILE_OFFSETS
+/* NB. Auto-generated from arch/.../asm-offsets.c */
+#include <asm/asm-offsets.h>
+#endif
+#include <asm/processor.h>
+
+#endif /* __ARM_ASM_DEFNS_H__ */
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "BSD"
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
--
1.7.2.5


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xensource.com
http://lists.xensource.com/xen-devel