diff options
Diffstat (limited to 'big-little/common/hyp_vectors.s')
-rw-r--r-- | big-little/common/hyp_vectors.s | 399 |
1 files changed, 399 insertions, 0 deletions
diff --git a/big-little/common/hyp_vectors.s b/big-little/common/hyp_vectors.s new file mode 100644 index 0000000..59d1b66 --- /dev/null +++ b/big-little/common/hyp_vectors.s @@ -0,0 +1,399 @@ + ; + ; Copyright (c) 2011, ARM Limited. All rights reserved. + ; + ; Redistribution and use in source and binary forms, with + ; or without modification, are permitted provided that the + ; following conditions are met: + ; + ; Redistributions of source code must retain the above + ; copyright notice, this list of conditions and the + ; following disclaimer. + ; + ; Redistributions in binary form must reproduce the + ; above copyright notice, this list of conditions and + ; the following disclaimer in the documentation + ; and/or other materials provided with the distribution. + ; + ; Neither the name of ARM nor the names of its + ; contributors may be used to endorse or promote products + ; derived from this software without specific prior written + ; permission. + ; + + AREA HypVectors, CODE, READONLY, ALIGN=5 + + PRESERVE8 + + IMPORT handle_interrupt + IMPORT HandleVirtualisor + IMPORT guestos_state + IMPORT guestos_state_size + IMPORT get_sp + IMPORT output_string + IMPORT virt_dead + IMPORT SetupVirtExtPageTables + IMPORT Enable2ndStagePageTables + IMPORT restore_context + IMPORT read_hsctlr + IMPORT write_hsctlr + IMPORT write_hmair0 + IMPORT write_httbr + IMPORT write_htcr + IMPORT bl_rest_init + IMPORT hyp_l1_pagetable + + IF ASYNC_SWITCH = {FALSE} + IMPORT is_hvc + IMPORT HandleHVC + ENDIF + + EXPORT vectors + EXPORT iabt_entry + EXPORT dabt_entry + EXPORT undef_entry + EXPORT svc_hyp_entry + EXPORT fiq_entry + EXPORT bl_setup + EXPORT hyp_warm_reset_handler + + + MACRO + hyp_entry $reg + SUB $reg, $reg, #72 + + ; --------------------------------------------------- + ; Save all GP registers + ; Save User mode LR which the HYP mode will use now. + ; Save HYP mode ELR & SPSR in case we are re-entrant + ; Pass saved context as argument to next bit of code + ; --------------------------------------------------- + STMIA $reg, {r0-r12} + MRS r0, ELR_hyp + MRS r1, SPSR + MRS r2, LR_usr + ADD r3, $reg, #60 + STMIA r3, {r0-r2} + MEND + + MACRO + hyp_exit $reg + ADD r3, $reg, #60 + LDMIA r3, {r0-r2} + MSR ELR_hyp, r0 + MSR SPSR_cxsf, r1 + MSR LR_usr, r2 + + ; ---------------------------------------------------- + ; We do need to clear the BTAC though since it is + ; virtually-addressed with no regard for the NS bit + ; ---------------------------------------------------- + MCR p15, 0, r0, c7, c5, 6 ; invalidate BTAC + + LDMIA $reg, {r0-r12} + ADD $reg, $reg, #72 + ERET + MEND + + IF {FALSE} +dabort_string + DCB " Virtualisor-DAB!\n", 0 +undef_string + DCB " Virtualisor-UND!\n", 0 +pabort_string + DCB " Virtualisor-PAB!\n", 0 +swi_string + DCB " Virtualisor-SWI!\n", 0 +irq_string + DCB " Virtualisor-IRQ!\n", 0 +fiq_string + DCB " Virtualisor-FIQ!\n", 0 +unused_string + DCB " Virtualisor-UNU!\n", 0 + + ALIGN + ENDIF + + ; ---------------------------------------------------- + ; Defines for enabling HYP mode MMU + ; ---------------------------------------------------- + +ENABLE EQU 0x1 +DISABLE EQU 0x0 + + ; ---------------------------------------------------- + ; HMAIR attributes relevant to us + ; ---------------------------------------------------- +HMAIR_INNER_WB_RWA_MEM EQU 0x0f +HMAIR_OUTER_WB_RWA_MEM EQU 0xf0 +HMAIR_DEVICE_MEM EQU 0x04 +HMAIR_SO_MEM EQU 0x00 + +IDX0 EQU (HMAIR_DEVICE_MEM << 0) +IDX1 EQU ((HMAIR_INNER_WB_RWA_MEM :OR: HMAIR_OUTER_WB_RWA_MEM) << 8) +IDX2 EQU (HMAIR_SO_MEM << 16) + + ; ---------------------------------------------------- + ; HSCTLR defines + ; ---------------------------------------------------- +ICACHE EQU (ENABLE << 12) +ALIGN EQU (ENABLE << 1) +DCACHE EQU (ENABLE << 2) +MMU EQU (ENABLE << 0) + + ; ---------------------------------------------------- + ; HTCR defines + ; ---------------------------------------------------- +CR_C_WBWA EQU 0x1 +CR_OUTER_SH EQU 0x2 +CR_INNER_SH EQU 0x3 +CR_ADDR_SPC_4GB EQU 0x0 + +EAE EQU (ENABLE << 31) +T0SZ EQU (CR_ADDR_SPC_4GB << 0) +IRGN0 EQU (CR_C_WBWA << 8) +ORGN0 EQU (CR_C_WBWA << 10) +SH0 EQU (CR_INNER_SH << 12) + +vectors + B bl_setup ; reset + B undef_entry ; undef + B svc_hyp_entry ; swi + B iabt_entry ; pabt + B dabt_entry ; dabt + B hvc_entry ; HVC + B irq_entry ; irq + B fiq_entry ; fiq + +bl_setup FUNCTION + ; ---------------------------------------------------- + ; This function is called after a reset. 'r0-r3' can + ; be corrupted after a cold reset. + ; Its also assumed that we are taking part in coherency + ; already (entered in secure world) + ; ---------------------------------------------------- + + ; ---------------------------------------------------- + ; Enable Caches + ; ---------------------------------------------------- + mrc p15, 4, r0, c1, c0, 0 + orr r0, #ICACHE + orr r0, #ALIGN + orr r0, #DCACHE + mcr p15, 4, r0, c1, c0, 0 + isb + + msr elr_hyp, lr + + ; ---------------------------------------------------- + ; Give yourself a stack without enabling the MMU so + ; that the pagetables can be created in C code. + ; ---------------------------------------------------- + + ; ---------------------------------------------------- + ; Allocate the HYP stack first up to do greater things + ; ---------------------------------------------------- + ldr r0, =guestos_state + ldr r1, =guestos_state_size + ldr r1, [r1] + bl get_sp + mov sp, r0 + + ; ---------------------------------------------------- + ; Create the 2nd stage and HYP mode page tables + ; ---------------------------------------------------- + bl SetupVirtExtPageTables + + ; ---------------------------------------------------- + ; Enable the HYP mode MMU before doing anything further + ; ---------------------------------------------------- + ldr r0, =hyp_l1_pagetable + MOV r1, #0 + mcrr p15, 4, r0, r1, c2 + ldr r0, =(IDX2 :OR: IDX1 :OR: IDX0) + mcr p15, 4, r0, c10, c2, 0 + ldr r0, =(EAE :OR: SH0 :OR: ORGN0 :OR: IRGN0 :OR: T0SZ) + mcr p15, 4, r0, c2, c0, 2 + mrc p15, 4, r0, c1, c0, 0 + orr r0, #MMU + mcr p15, 4, r0, c1, c0, 0 + dsb + isb + + ; ---------------------------------------------------- + ; Initialise the remaining bits now that the MMU is on + ; ---------------------------------------------------- + hyp_entry sp + bl bl_rest_init + hyp_exit sp + + ENDFUNC + + IF {FALSE} +common_abt + PUSH {lr} + + BL hexword ; print r0 + + MRC p15, 0, r0, c5, c0, 0 ; DFSR + BL hexword + + MRC p15, 0, r0, c6, c0, 0 ; DFAR + BL hexword + + MRC p15, 4, r0, c5, c2, 0 ; HSR + BL hexword + + MRC p15, 4, r0, c6, c0, 0 ; HDFAR + BL hexword + + MRC p15, 4, r0, c6, c0, 2 ; HIFAR + BL hexword + + MRC p15, 4, r0, c6, c0, 4 ; HPFAR + BL hexword + + POP {lr} + BX lr + +dabt_entry + MOV r0, lr ; save lr, just in case it's interesting + IF {FALSE} + BL common_abt + ENDIF + LDR r0, =dabort_string + BL output_string + B dead + +iabt_entry + MOV r0, lr ; save lr, just in case it's interesting + IF {FALSE} + BL common_abt + ENDIF + LDR r0, =pabort_string + BL output_string + B dead + +undef_entry + MOV r0, lr ; save lr, just in case it's interesting + IF {FALSE} + BL common_abt + ENDIF + LDR r0, =undef_string + BL output_string + B dead + +dead + B dead + ENDIF + +dabt_entry + B dabt_entry + +iabt_entry + B iabt_entry + +undef_entry + B undef_entry + +irq_entry + hyp_entry sp + ; ---------------------------------------------------- + ; Pass SP as arg if we intend to initiate a switchover + ; ---------------------------------------------------- + MOV r0, sp + BL handle_interrupt + hyp_exit sp + +svc_hyp_entry + B svc_hyp_entry + +fiq_entry + B fiq_entry + +hvc_entry + hyp_entry sp + + ; ---------------------------------------------------- + ; Check if we have an HVC call. The Switcher handles + ; it first. If its unable to, its passed to the + ; Virtualisor. It should be possible to cascade an HVC + ; across the two, but not for the time being. + ; ---------------------------------------------------- + IF ASYNC_SWITCH = {FALSE} + BL is_hvc + CMP r0, #0 + BEQ next + MOV r0, sp + BL HandleHVC + TST r0, #1 + BNE out + ENDIF +next + MOV r0, sp + BL HandleVirtualisor +out + hyp_exit sp + +hyp_warm_reset_handler FUNCTION + ; ---------------------------------------------------- + ; Enable Caches + ; ---------------------------------------------------- + mrc p15, 4, r0, c1, c0, 0 + orr r0, #ICACHE + orr r0, #ALIGN + orr r0, #DCACHE + mcr p15, 4, r0, c1, c0, 0 + isb + + ; ---------------------------------------------------- + ; Enable the HYP mode MMU before doing anything further + ; ---------------------------------------------------- + ldr r0, =hyp_l1_pagetable + MOV r1, #0 + mcrr p15, 4, r0, r1, c2 + ldr r0, =(IDX2 :OR: IDX1 :OR: IDX0) + mcr p15, 4, r0, c10, c2, 0 + ldr r0, =(EAE :OR: SH0 :OR: ORGN0 :OR: IRGN0 :OR: T0SZ) + mcr p15, 4, r0, c2, c0, 2 + mrc p15, 4, r0, c1, c0, 0 + orr r0, #MMU + mcr p15, 4, r0, c1, c0, 0 + dsb + isb + + ; ---------------------------------------------------- + ; Initialise the remaining bits now that the MMU is on + ; ---------------------------------------------------- + + ; ---------------------------------------------------- + ; Allocate the HYP stack first up to do greater things + ; ---------------------------------------------------- + ldr r0, =guestos_state + ldr r1, =guestos_state_size + ldr r1, [r1] + bl get_sp + mov sp, r0 + + ; ---------------------------------------------------- + ; Initialise the HVBAR + ; ---------------------------------------------------- + adr r0, vectors + mcr p15, 4, r0, c12, c0, 0 + + ; ---------------------------------------------------- + ; Initialise the 2nd stage translations for NS PL0/1 + ; ---------------------------------------------------- + bl Enable2ndStagePageTables + + ; ---------------------------------------------------- + ; Restore the context now. CPU0 is the first cpu + ; ---------------------------------------------------- + hyp_entry sp + mov r0, #0 + bl restore_context + hyp_exit sp + + ENDFUNC + + END + |