Changeset View
Changeset View
Standalone View
Standalone View
sys/arm/arm/locore-v6.S
Show All 29 Lines | |||||
#include "assym.s" | #include "assym.s" | ||||
#include <sys/syscall.h> | #include <sys/syscall.h> | ||||
#include <machine/asm.h> | #include <machine/asm.h> | ||||
#include <machine/asmacros.h> | #include <machine/asmacros.h> | ||||
#include <machine/armreg.h> | #include <machine/armreg.h> | ||||
#include <machine/sysreg.h> | #include <machine/sysreg.h> | ||||
#include <machine/pte-v6.h> | #include <machine/pte-v6.h> | ||||
__FBSDID("$FreeBSD$"); | |||||
__FBSDID("$FreeBSD$"); | |||||
#if __ARM_ARCH >= 7 | #if __ARM_ARCH >= 7 | ||||
#if defined(__ARM_ARCH_7VE__) || defined(__clang__) | #if defined(__ARM_ARCH_7VE__) || defined(__clang__) | ||||
/* | /* | ||||
* HYP support is in bintuils >= 2.21 and gcc >= 4.9 defines __ARM_ARCH_7VE__ | * HYP support is in bintuils >= 2.21 and gcc >= 4.9 defines __ARM_ARCH_7VE__ | ||||
* when enabled. llvm >= 3.6 supports it too. | |||||
*/ | |||||
.arch_extension virt | |||||
#define MSR_ELR_HYP(regnum) msr elr_hyp, lr | |||||
#define ERET eret | |||||
#else | * when enabled. llvm >= 3.6 supports it too. | ||||
#define MSR_ELR_HYP(regnum) .word (0xe12ef300 | regnum) | */ | ||||
#define ERET .word 0xe160006e | .arch_extension virt | ||||
#endif | #endif | ||||
#endif /* __ARM_ARCH >= 7 */ | #endif /* __ARM_ARCH >= 7 */ | ||||
/* A small statically-allocated stack used only during initarm() and AP startup. */ | /* A small statically-allocated stack used only during initarm() and AP startup. */ | ||||
#define INIT_ARM_STACK_SIZE 2048 | #define INIT_ARM_STACK_SIZE 2048 | ||||
.text | .text | ||||
.align 2 | .align 2 | ||||
#if __ARM_ARCH >= 7 | #if __ARM_ARCH >= 7 | ||||
#define HANDLE_HYP \ | |||||
/* Leave HYP mode */ ;\ | |||||
mrs r0, cpsr ;\ | |||||
and r0, r0, #(PSR_MODE) /* Mode is in the low 5 bits of CPSR */ ;\ | |||||
teq r0, #(PSR_HYP32_MODE) /* Hyp Mode? */ ;\ | |||||
#define LEAVE_HYP \ | bne 1f ;\ | ||||
/* Leave HYP mode */ ;\ | /* Install Hypervisor Stub Exception Vector */ ;\ | ||||
mrs r0, cpsr ;\ | bl hypervisor_stub_vect_install ;\ | ||||
and r0, r0, #(PSR_MODE) /* Mode is in the low 5 bits of CPSR */ ;\ | mov r0, 0 ;\ | ||||
teq r0, #(PSR_HYP32_MODE) /* Hyp Mode? */ ;\ | adr r1, hypmode_enabled ;\ | ||||
bne 1f ;\ | str r0, [r1] ;\ | ||||
/* Ensure that IRQ, FIQ and Aborts will be disabled after eret */ ;\ | /* Ensure that IRQ, FIQ and Aborts will be disabled after eret */ ;\ | ||||
andrew: I think we should be passing this to initarm via the `struct arm_boot_params *`. Although I… | |||||
mrs r0, cpsr ;\ | mrs r0, cpsr ;\ | ||||
bic r0, r0, #(PSR_MODE) ;\ | bic r0, r0, #(PSR_MODE) ;\ | ||||
orr r0, r0, #(PSR_SVC32_MODE) ;\ | orr r0, r0, #(PSR_SVC32_MODE) ;\ | ||||
orr r0, r0, #(PSR_I | PSR_F | PSR_A) ;\ | orr r0, r0, #(PSR_I | PSR_F | PSR_A) ;\ | ||||
msr spsr_cxsf, r0 ;\ | |||||
/* Exit hypervisor mode */ ;\ | |||||
adr lr, 2f ;\ | |||||
MSR_ELR_HYP(14) ;\ | |||||
msr spsr_cxsf, r0 ;\ | ERET ;\ | ||||
/* Exit hypervisor mode */ ;\ | 1: ;\ | ||||
adr lr, 1f ;\ | mov r0, -1 ;\ | ||||
MSR_ELR_HYP(14) ;\ | adr r1, hypmode_enabled ;\ | ||||
ERET ;\ | str r0, [r1] ;\ | ||||
1: | 2: | ||||
#else | #else | ||||
#define LEAVE_HYP | #define HANDLE_HYP | ||||
#endif /* __ARM_ARCH >= 7 */ | #endif /* __ARM_ARCH >= 7 */ | ||||
/* | /* | ||||
* On entry for FreeBSD boot ABI: | * On entry for FreeBSD boot ABI: | ||||
* r0 - metadata pointer or 0 (boothowto on AT91's boot2) | * r0 - metadata pointer or 0 (boothowto on AT91's boot2) | ||||
* r1 - if (r0 == 0) then metadata pointer | * r1 - if (r0 == 0) then metadata pointer | ||||
* On entry for Linux boot ABI: | * On entry for Linux boot ABI: | ||||
* r0 - 0 | * r0 - 0 | ||||
* r1 - machine type (passed as arg2 to initarm) | * r1 - machine type (passed as arg2 to initarm) | ||||
* r2 - Pointer to a tagged list or dtb image (phys addr) (passed as arg1 initarm) | * r2 - Pointer to a tagged list or dtb image (phys addr) (passed as arg1 initarm) | ||||
* | * | ||||
* For both types of boot we gather up the args, put them in a struct arm_boot_params | * For both types of boot we gather up the args, put them in a struct arm_boot_params | ||||
* structure and pass that to initarm. | * structure and pass that to initarm. | ||||
*/ | */ | ||||
.globl btext | .globl btext | ||||
btext: | btext: | ||||
ASENTRY_NP(_start) | ASENTRY_NP(_start) | ||||
STOP_UNWINDING /* Can't unwind into the bootloader! */ | STOP_UNWINDING /* Can't unwind into the bootloader! */ | ||||
/* Make sure interrupts are disabled. */ | |||||
/* Make sure interrupts are disabled. */ | cpsid ifa | ||||
cpsid ifa | |||||
mov r8, r0 /* 0 or boot mode from boot2 */ | |||||
mov r8, r0 /* 0 or boot mode from boot2 */ | mov r9, r1 /* Save Machine type */ | ||||
mov r9, r1 /* Save Machine type */ | mov r10, r2 /* Save meta data */ | ||||
mov r10, r2 /* Save meta data */ | mov r11, r3 /* Future expansion */ | ||||
mov r11, r3 /* Future expansion */ | |||||
# If HYP-MODE is active, install an exception vector stub | |||||
LEAVE_HYP | HANDLE_HYP | ||||
/* | /* | ||||
* Check whether data cache is enabled. If it is, then we know | * Check whether data cache is enabled. If it is, then we know | ||||
* current tags are valid (not power-on garbage values) and there | * current tags are valid (not power-on garbage values) and there | ||||
* might be dirty lines that need cleaning. Disable cache to prevent | * might be dirty lines that need cleaning. Disable cache to prevent | ||||
* new lines being allocated, then call wbinv_poc_all to clean it. | * new lines being allocated, then call wbinv_poc_all to clean it. | ||||
*/ | */ | ||||
mrc CP15_SCTLR(r7) | mrc CP15_SCTLR(r7) | ||||
▲ Show 20 Lines • Show All 235 Lines • ▼ Show 20 Lines | #endif | ||||
mcr CP15_SCTLR(r7) | mcr CP15_SCTLR(r7) | ||||
DSB | DSB | ||||
mcr CP15_TTBR0(r4) /* Set new TTB */ | mcr CP15_TTBR0(r4) /* Set new TTB */ | ||||
DSB | DSB | ||||
ISB | ISB | ||||
mcr CP15_TLBIALL /* Flush TLB */ | mcr CP15_TLBIALL /* Flush TLB */ | ||||
mcr CP15_BPIALL /* Flush Branch predictor */ | |||||
DSB | |||||
ISB | |||||
mcr CP15_BPIALL /* Flush Branch predictor */ | |||||
DSB | #if 0 /* XXX writeback shouldn't be necessary */ | ||||
ISB | /* Write back and invalidate all integrated caches */ | ||||
bl dcache_wbinv_poc_all | |||||
#if 0 /* XXX writeback shouldn't be necessary */ | #else | ||||
/* Write back and invalidate all integrated caches */ | bl dcache_inv_pou_all | ||||
bl dcache_wbinv_poc_all | #endif | ||||
#else | mcr CP15_ICIALLU | ||||
bl dcache_inv_pou_all | DSB | ||||
#endif | ISB | ||||
mcr CP15_ICIALLU | |||||
DSB | pop {r4-r11, pc} | ||||
ISB | END(reinit_mmu) | ||||
pop {r4-r11, pc} | |||||
END(reinit_mmu) | /* | ||||
* Builds the page table | |||||
* r0 - The table base address | |||||
/* | * r1 - The physical address (trashed) | ||||
* Builds the page table | * r2 - The virtual address (trashed) | ||||
* r0 - The table base address | * r3 - The number of 1MiB sections | ||||
* r1 - The physical address (trashed) | * r4 - Trashed | ||||
* r2 - The virtual address (trashed) | * | ||||
* r3 - The number of 1MiB sections | * Addresses must be 1MiB aligned | ||||
* r4 - Trashed | */ | ||||
* | build_device_pagetables: | ||||
* Addresses must be 1MiB aligned | ldr r4, =PTE1_V|PTE1_A|PTE1_AP_KRW|TEX1_CLASS_0 | ||||
*/ | b 1f | ||||
build_device_pagetables: | build_pagetables: | ||||
ldr r4, =PTE1_V|PTE1_A|PTE1_AP_KRW|TEX1_CLASS_0 | /* Set the required page attributed */ | ||||
b 1f | ldr r4, =PTE1_V|PTE1_A|PTE1_AP_KRW|TEX1_CLASS_0 | ||||
build_pagetables: | 1: | ||||
/* Set the required page attributed */ | orr r1, r4 | ||||
ldr r4, =PTE1_V|PTE1_A|PTE1_AP_KRW|TEX1_CLASS_0 | |||||
1: | /* Move the virtual address to the correct bit location */ | ||||
orr r1, r4 | lsr r2, #(PTE1_SHIFT - 2) | ||||
/* Move the virtual address to the correct bit location */ | mov r4, r3 | ||||
lsr r2, #(PTE1_SHIFT - 2) | 2: | ||||
str r1, [r0, r2] | |||||
mov r4, r3 | add r2, r2, #4 | ||||
2: | add r1, r1, #(PTE1_SIZE) | ||||
str r1, [r0, r2] | adds r4, r4, #-1 | ||||
add r2, r2, #4 | bhi 2b | ||||
add r1, r1, #(PTE1_SIZE) | |||||
adds r4, r4, #-1 | mov pc, lr | ||||
bhi 2b | |||||
VA_TO_PA_POINTER(Lpagetable, boot_pt1) | |||||
mov pc, lr | |||||
.global _C_LABEL(hypmode_enabled) | |||||
VA_TO_PA_POINTER(Lpagetable, boot_pt1) | _C_LABEL(hypmode_enabled): | ||||
.word 0 | |||||
.Lstart: | .Lstart: | ||||
.word _edata /* Note that these three items are */ | .word _edata /* Note that these three items are */ | ||||
.word _ebss /* loaded with a single ldmia and */ | .word _ebss /* loaded with a single ldmia and */ | ||||
.word svcstk /* must remain in order together. */ | .word svcstk /* must remain in order together. */ | ||||
.Lmainreturned: | .Lmainreturned: | ||||
.asciz "main() returned" | .asciz "main() returned" | ||||
Show All 17 Lines | boot_pt1: | ||||
.align 2 | .align 2 | ||||
#if defined(SMP) | #if defined(SMP) | ||||
ASENTRY_NP(mpentry) | ASENTRY_NP(mpentry) | ||||
/* Make sure interrupts are disabled. */ | /* Make sure interrupts are disabled. */ | ||||
cpsid ifa | cpsid ifa | ||||
LEAVE_HYP | HANDLE_HYP | ||||
/* Setup core, disable all caches. */ | /* Setup core, disable all caches. */ | ||||
mrc CP15_SCTLR(r0) | mrc CP15_SCTLR(r0) | ||||
bic r0, #CPU_CONTROL_MMU_ENABLE | bic r0, #CPU_CONTROL_MMU_ENABLE | ||||
bic r0, #CPU_CONTROL_AFLT_ENABLE | bic r0, #CPU_CONTROL_AFLT_ENABLE | ||||
bic r0, #CPU_CONTROL_DC_ENABLE | bic r0, #CPU_CONTROL_DC_ENABLE | ||||
bic r0, #CPU_CONTROL_IC_ENABLE | bic r0, #CPU_CONTROL_IC_ENABLE | ||||
bic r0, #CPU_CONTROL_BPRD_ENABLE | bic r0, #CPU_CONTROL_BPRD_ENABLE | ||||
▲ Show 20 Lines • Show All 127 Lines • Show Last 20 Lines |
I think we should be passing this to initarm via the struct arm_boot_params *. Although I note we are running low on free registers.