219d14fe5f
Executive is a library that can be used by standalone applications and kernels to abstract access to Octeon SoC and board-specific hardware and facilities. The FreeBSD port to Octeon will be updated to use this where possible.
182 lines
5.5 KiB
ArmAsm
182 lines
5.5 KiB
ArmAsm
/***********************license start***************
|
|
* Copyright (c) 2003-2008 Cavium Networks (support@cavium.com). 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 Cavium Networks nor the names of
|
|
* its contributors may be used to endorse or promote products
|
|
* derived from this software without specific prior written
|
|
* permission.
|
|
*
|
|
* TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
|
|
* AND WITH ALL FAULTS AND CAVIUM NETWORKS MAKES NO PROMISES, REPRESENTATIONS
|
|
* OR WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH
|
|
* RESPECT TO THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY
|
|
* REPRESENTATION OR DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT
|
|
* DEFECTS, AND CAVIUM SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES
|
|
* OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR
|
|
* PURPOSE, LACK OF VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT, QUIET
|
|
* POSSESSION OR CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK ARISING OUT
|
|
* OF USE OR PERFORMANCE OF THE SOFTWARE LIES WITH YOU.
|
|
*
|
|
*
|
|
* For any questions regarding licensing please contact marketing@caviumnetworks.com
|
|
*
|
|
***********************license end**************************************/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#include <machine/asm.h>
|
|
#include <machine/regdef.h>
|
|
|
|
.set noreorder
|
|
.set noat
|
|
|
|
LEAF(cvmx_interrupt_stage1)
|
|
dla k0, cvmx_interrupt_stage2
|
|
jalr k1, k0 // Save our address in k1, so we can tell which
|
|
// vector we are coming from.
|
|
nop
|
|
END(cvmx_interrupt_stage1)
|
|
|
|
#define STACK_SIZE (36*8)
|
|
LEAF(cvmx_interrupt_stage2)
|
|
dsubu sp, sp, STACK_SIZE
|
|
sd zero, 0(sp) // Just a place holder
|
|
sd $1, 8(sp) // start saving registers
|
|
sd $2, 16(sp)
|
|
sd $3, 24(sp)
|
|
sd $4, 32(sp)
|
|
sd $5, 40(sp)
|
|
sd $6, 48(sp)
|
|
sd $7, 56(sp)
|
|
sd $8, 64(sp)
|
|
sd $9, 72(sp)
|
|
sd $10, 80(sp)
|
|
sd $11, 88(sp)
|
|
sd $12, 96(sp)
|
|
sd $13, 104(sp)
|
|
sd $14, 112(sp)
|
|
sd $15, 120(sp)
|
|
sd $16, 128(sp)
|
|
sd $17, 136(sp)
|
|
sd $18, 144(sp)
|
|
sd $19, 152(sp)
|
|
sd $20, 160(sp)
|
|
sd $21, 168(sp)
|
|
sd $22, 176(sp)
|
|
sd $23, 184(sp)
|
|
sd $24, 192(sp)
|
|
sd $25, 200(sp)
|
|
sd $26, 208(sp)
|
|
sd $27, 216(sp)
|
|
mfhi k0 // Reading lo and high takes multiple cycles
|
|
mflo k1 // Do it here so it completes by the time we need it
|
|
sd $28, 224(sp)
|
|
daddu $1, sp, STACK_SIZE // Correct the SP for the space we used
|
|
sd $1, 232(sp)
|
|
sd $30, 240(sp)
|
|
sd $31, 248(sp) // saved all general purpose registers
|
|
sd k0, 256(sp) // save hi
|
|
sd k1, 264(sp) // save lo
|
|
/* Save DCACHE error register early, since any non-errored DCACHE accesses will clear
|
|
** error bit */
|
|
dmfc0 k0, $27, 1
|
|
sd k0, 272(sp)
|
|
/* Store DEPC for GCC's frame unwinder. */
|
|
dmfc0 k0, $14
|
|
sd k0, 280(sp)
|
|
|
|
dla k0, cvmx_interrupt_do_irq
|
|
jal k0
|
|
dadd a0, sp, 0 // First argument is array of registers
|
|
|
|
ld k0, 256(sp) // read hi
|
|
ld k1, 264(sp) // read lo
|
|
mthi k0 // restore hi
|
|
mtlo k1 // restore lo
|
|
|
|
ld $1, 8(sp) // start restoring registers
|
|
ld $2, 16(sp)
|
|
ld $3, 24(sp)
|
|
ld $4, 32(sp)
|
|
ld $5, 40(sp)
|
|
ld $6, 48(sp)
|
|
ld $7, 56(sp)
|
|
ld $8, 64(sp)
|
|
ld $9, 72(sp)
|
|
ld $10, 80(sp)
|
|
ld $11, 88(sp)
|
|
ld $12, 96(sp)
|
|
ld $13, 104(sp)
|
|
ld $14, 112(sp)
|
|
ld $15, 120(sp)
|
|
ld $16, 128(sp)
|
|
ld $17, 136(sp)
|
|
ld $18, 144(sp)
|
|
ld $19, 152(sp)
|
|
ld $20, 160(sp)
|
|
ld $21, 168(sp)
|
|
ld $22, 176(sp)
|
|
ld $23, 184(sp)
|
|
ld $24, 192(sp)
|
|
ld $25, 200(sp)
|
|
ld $26, 208(sp)
|
|
ld $28, 224(sp)
|
|
ld $30, 240(sp)
|
|
ld $31, 248(sp) // restored all general purpose registers
|
|
ld $29, 232(sp) // No need to correct for STACK_SIZE
|
|
eret
|
|
nop
|
|
END(cvmx_interrupt_stage2)
|
|
|
|
// Icache and Dcache exception handler. This code is executed
|
|
// with ERL set so we can't us virtual addresses. We save and restore
|
|
// K0 to a global memory location so we can handle cache errors from exception
|
|
// context. This means that if two cores get a cache exception at the same time
|
|
// the K0 might be corrupted. This entire handler MUST fit in 128 bytes.
|
|
#define K0_STORE_LOCATION 8
|
|
#define DCACHE_ERROR_COUNT 16
|
|
#define ICACHE_ERROR_COUNT 24
|
|
LEAF(cvmx_interrupt_cache_error)
|
|
.set push
|
|
.set noreorder
|
|
sd k0, K0_STORE_LOCATION($0) // Store K0 into global loc in case we're in an exception
|
|
dmfc0 k0, $27, 1 // Get Dcache error status before any loads
|
|
bbit0 k0, 0, not_dcache_error // Skip dcache count if no error
|
|
dmtc0 k0, $27, 1 // Clear any Dcache errors
|
|
ld k0, DCACHE_ERROR_COUNT($0) // Load the dcache error count
|
|
daddu k0, 1 // Increment the dcache error count
|
|
sd k0, DCACHE_ERROR_COUNT($0) // Store the dcache error count
|
|
not_dcache_error:
|
|
dmfc0 k0, $27, 0 // Get the Icache error status
|
|
bbit0 k0, 0, not_icache_error // Skip Icache count if no error
|
|
dmtc0 k0, $27, 0 // Clear any Icache errors
|
|
ld k0, ICACHE_ERROR_COUNT($0) // Load the icache error count
|
|
daddu k0, 1 // Increment the icache error count
|
|
sd k0, ICACHE_ERROR_COUNT($0) // Store the icache error count
|
|
not_icache_error:
|
|
ld k0, K0_STORE_LOCATION($0) // Restore K0 since we might have been in an exception
|
|
eret // Return from the Icache exception
|
|
.set pop
|
|
END(cvmx_interrupt_cache_error)
|
|
|