[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [PATCH v6 11/27] arm: entry.S and head.S
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@xxxxxxxxxxxxx> Signed-off-by: Ian Campbell <ian.campbell@xxxxxxxxxx> Signed-off-by: Tim Deegan <Tim.Deegan@xxxxxxxxxx> --- 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 +++ 6 files changed, 712 insertions(+), 0 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/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@xxxxxxx> + * 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@xxxxxxxxxxxxxxxxxxxxxxxx> */ +/* 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@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |