mirror of
https://github.com/xen-project/xen.git
synced 2026-10-28 02:01:24 +01:00
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@eu.citrix.com> Signed-off-by: Ian Campbell <ian.campbell@citrix.com> Signed-off-by: Tim Deegan <Tim.Deegan@citrix.com> Committed-by: Ian Campbell <ian.campbell@citrix.com>
This commit is contained in:
1 parent
e98c8b548b
commit
5da0d3123c
6 files changed
+712
No files matched your search
@@ -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:
|
||||
*/
|
||||
@@ -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);
|
||||
@@ -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
|
||||
@@ -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 */
|
||||
@@ -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) }
|
||||
}
|
||||
@@ -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:
|
||||
*/
|
||||