kernel-fxtec-pro1x/arch/arc/kernel/entry-arcv2.S
Vineet Gupta 3971cdc202 ARC: boot: Support Halt-on-reset and Run-on-reset SMP booting modes
For Run-on-reset, non masters need to spin wait. For Halt-on-reset they
can jump to entry point directly.

Also while at it, made reset vector handler as "the" entry point for
kernel including host debugger based boot (which uses the ELF header
entry point)

Signed-off-by: Vineet Gupta <vgupta@synopsys.com>
2015-10-28 16:08:17 +05:30

234 lines
5.5 KiB
ArmAsm

/*
* ARCv2 ISA based core Low Level Intr/Traps/Exceptions(non-TLB) Handling
*
* Copyright (C) 2013 Synopsys, Inc. (www.synopsys.com)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <linux/linkage.h> /* ARC_{EXTRY,EXIT} */
#include <asm/entry.h> /* SAVE_ALL_{INT1,INT2,TRAP...} */
#include <asm/errno.h>
#include <asm/arcregs.h>
#include <asm/irqflags.h>
.cpu HS
#define VECTOR .word
;############################ Vector Table #################################
.section .vector,"a",@progbits
.align 4
# Initial 16 slots are Exception Vectors
VECTOR res_service ; Reset Vector
VECTOR mem_service ; Mem exception
VECTOR instr_service ; Instrn Error
VECTOR EV_MachineCheck ; Fatal Machine check
VECTOR EV_TLBMissI ; Intruction TLB miss
VECTOR EV_TLBMissD ; Data TLB miss
VECTOR EV_TLBProtV ; Protection Violation
VECTOR EV_PrivilegeV ; Privilege Violation
VECTOR EV_SWI ; Software Breakpoint
VECTOR EV_Trap ; Trap exception
VECTOR EV_Extension ; Extn Instruction Exception
VECTOR EV_DivZero ; Divide by Zero
VECTOR EV_DCError ; Data Cache Error
VECTOR EV_Misaligned ; Misaligned Data Access
VECTOR reserved ; Reserved slots
VECTOR reserved ; Reserved slots
# Begin Interrupt Vectors
VECTOR handle_interrupt ; (16) Timer0
VECTOR handle_interrupt ; unused (Timer1)
VECTOR handle_interrupt ; unused (WDT)
VECTOR handle_interrupt ; (19) ICI (inter core interrupt)
VECTOR handle_interrupt
VECTOR handle_interrupt
VECTOR handle_interrupt
VECTOR handle_interrupt ; (23) End of fixed IRQs
.rept CONFIG_ARC_NUMBER_OF_INTERRUPTS - 8
VECTOR handle_interrupt
.endr
.section .text, "ax",@progbits
reserved:
flag 1 ; Unexpected event, halt
;##################### Interrupt Handling ##############################
ENTRY(handle_interrupt)
INTERRUPT_PROLOGUE irq
clri ; To make status32.IE agree with CPU internal state
lr r0, [ICAUSE]
mov blink, ret_from_exception
b.d arch_do_IRQ
mov r1, sp
END(handle_interrupt)
;################### Non TLB Exception Handling #############################
ENTRY(EV_SWI)
flag 1
END(EV_SWI)
ENTRY(EV_DivZero)
flag 1
END(EV_DivZero)
ENTRY(EV_DCError)
flag 1
END(EV_DCError)
ENTRY(EV_Misaligned)
EXCEPTION_PROLOGUE
lr r0, [efa] ; Faulting Data address
mov r1, sp
FAKE_RET_FROM_EXCPN
SAVE_CALLEE_SAVED_USER
mov r2, sp ; callee_regs
bl do_misaligned_access
; TBD: optimize - do this only if a callee reg was involved
; either a dst of emulated LD/ST or src with address-writeback
RESTORE_CALLEE_SAVED_USER
b ret_from_exception
END(EV_Misaligned)
; ---------------------------------------------
; Protection Violation Exception Handler
; ---------------------------------------------
ENTRY(EV_TLBProtV)
EXCEPTION_PROLOGUE
lr r0, [efa] ; Faulting Data address
mov r1, sp ; pt_regs
FAKE_RET_FROM_EXCPN
mov blink, ret_from_exception
b do_page_fault
END(EV_TLBProtV)
; From Linux standpoint Slow Path I/D TLB Miss is same a ProtV as they
; need to call do_page_fault().
; ECR in pt_regs provides whether access was R/W/X
.global call_do_page_fault
.set call_do_page_fault, EV_TLBProtV
;############# Common Handlers for ARCompact and ARCv2 ##############
#include "entry.S"
;############# Return from Intr/Excp/Trap (ARCv2 ISA Specifics) ##############
;
; Restore the saved sys context (common exit-path for EXCPN/IRQ/Trap)
; IRQ shd definitely not happen between now and rtie
; All 2 entry points to here already disable interrupts
.Lrestore_regs:
ld r0, [sp, PT_status32] ; U/K mode at time of entry
lr r10, [AUX_IRQ_ACT]
bmsk r11, r10, 15 ; AUX_IRQ_ACT.ACTIVE
breq r11, 0, .Lexcept_ret ; No intr active, ret from Exception
;####### Return from Intr #######
debug_marker_l1:
bbit1.nt r0, STATUS_DE_BIT, .Lintr_ret_to_delay_slot
.Lisr_ret_fast_path:
; Handle special case #1: (Entry via Exception, Return via IRQ)
;
; Exception in U mode, preempted in kernel, Intr taken (K mode), orig
; task now returning to U mode (riding the Intr)
; AUX_IRQ_ACTIVE won't have U bit set (since intr in K mode), hence SP
; won't be switched to correct U mode value (from AUX_SP)
; So force AUX_IRQ_ACT.U for such a case
btst r0, STATUS_U_BIT ; Z flag set if K (Z clear for U)
bset.nz r11, r11, AUX_IRQ_ACT_BIT_U ; NZ means U
sr r11, [AUX_IRQ_ACT]
INTERRUPT_EPILOGUE irq
rtie
;####### Return from Exception / pure kernel mode #######
.Lexcept_ret: ; Expects r0 has PT_status32
debug_marker_syscall:
EXCEPTION_EPILOGUE
rtie
;####### Return from Intr to insn in delay slot #######
; Handle special case #2: (Entry via Exception in Delay Slot, Return via IRQ)
;
; Intr returning to a Delay Slot (DS) insn
; (since IRQ NOT allowed in DS in ARCv2, this can only happen if orig
; entry was via Exception in DS which got preempted in kernel).
;
; IRQ RTIE won't reliably restore DE bit and/or BTA, needs handling
.Lintr_ret_to_delay_slot:
debug_marker_ds:
ld r2, [@intr_to_DE_cnt]
add r2, r2, 1
st r2, [@intr_to_DE_cnt]
ld r2, [sp, PT_ret]
ld r3, [sp, PT_status32]
bic r0, r3, STATUS_U_MASK|STATUS_DE_MASK|STATUS_IE_MASK|STATUS_L_MASK
st r0, [sp, PT_status32]
mov r1, .Lintr_ret_to_delay_slot_2
st r1, [sp, PT_ret]
st r2, [sp, 0]
st r3, [sp, 4]
b .Lisr_ret_fast_path
.Lintr_ret_to_delay_slot_2:
sub sp, sp, SZ_PT_REGS
st r9, [sp, -4]
ld r9, [sp, 0]
sr r9, [eret]
ld r9, [sp, 4]
sr r9, [erstatus]
ld r9, [sp, 8]
sr r9, [erbta]
ld r9, [sp, -4]
add sp, sp, SZ_PT_REGS
rtie
END(ret_from_exception)