1215976Sjmallett/***********************license start*************** 2232812Sjmallett * Copyright (c) 2003-2010 Cavium Inc. (support@cavium.com). All rights 3215976Sjmallett * reserved. 4215976Sjmallett * 5215976Sjmallett * 6215976Sjmallett * Redistribution and use in source and binary forms, with or without 7215976Sjmallett * modification, are permitted provided that the following conditions are 8215976Sjmallett * met: 9215976Sjmallett * 10215976Sjmallett * * Redistributions of source code must retain the above copyright 11215976Sjmallett * notice, this list of conditions and the following disclaimer. 12215976Sjmallett * 13215976Sjmallett * * Redistributions in binary form must reproduce the above 14215976Sjmallett * copyright notice, this list of conditions and the following 15215976Sjmallett * disclaimer in the documentation and/or other materials provided 16215976Sjmallett * with the distribution. 17215976Sjmallett 18232812Sjmallett * * Neither the name of Cavium Inc. nor the names of 19215976Sjmallett * its contributors may be used to endorse or promote products 20215976Sjmallett * derived from this software without specific prior written 21215976Sjmallett * permission. 22215976Sjmallett 23215976Sjmallett * This Software, including technical data, may be subject to U.S. export control 24215976Sjmallett * laws, including the U.S. Export Administration Act and its associated 25215976Sjmallett * regulations, and may be subject to export or import regulations in other 26215976Sjmallett * countries. 27215976Sjmallett 28215976Sjmallett * TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS" 29232812Sjmallett * AND WITH ALL FAULTS AND CAVIUM INC. MAKES NO PROMISES, REPRESENTATIONS OR 30215976Sjmallett * WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT TO 31215976Sjmallett * THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY REPRESENTATION OR 32215976Sjmallett * DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT DEFECTS, AND CAVIUM 33215976Sjmallett * SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES OF TITLE, 34215976Sjmallett * MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR PURPOSE, LACK OF 35215976Sjmallett * VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT, QUIET POSSESSION OR 36215976Sjmallett * CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK ARISING OUT OF USE OR 37215976Sjmallett * PERFORMANCE OF THE SOFTWARE LIES WITH YOU. 38215976Sjmallett ***********************license end**************************************/ 39215976Sjmallett 40215976Sjmallett 41215976Sjmallett 42215976Sjmallett 43215976Sjmallett 44215976Sjmallett 45215976Sjmallett 46215976Sjmallett 47215976Sjmallett 48215976Sjmallett 49215976Sjmallett#include <machine/asm.h> 50215976Sjmallett#include <machine/regdef.h> 51215976Sjmallett 52215976Sjmallett.set noreorder 53215976Sjmallett.set noat 54215976Sjmallett 55215976SjmallettLEAF(cvmx_interrupt_stage1) 56215976Sjmallett dla k0, cvmx_interrupt_stage2 57215976Sjmallett jalr k1, k0 // Save our address in k1, so we can tell which 58215976Sjmallett // vector we are coming from. 59215976Sjmallett nop 60215976SjmallettEND(cvmx_interrupt_stage1) 61215976Sjmallett 62215976Sjmallett#define STACK_SIZE (36*8) 63215976SjmallettLEAF(cvmx_interrupt_stage2) 64215976Sjmallett dsubu sp, sp, STACK_SIZE 65215976Sjmallett sd zero, 0(sp) // Just a place holder 66215976Sjmallett sd $1, 8(sp) // start saving registers 67215976Sjmallett sd $2, 16(sp) 68215976Sjmallett sd $3, 24(sp) 69215976Sjmallett sd $4, 32(sp) 70215976Sjmallett sd $5, 40(sp) 71215976Sjmallett sd $6, 48(sp) 72215976Sjmallett sd $7, 56(sp) 73215976Sjmallett sd $8, 64(sp) 74215976Sjmallett sd $9, 72(sp) 75215976Sjmallett sd $10, 80(sp) 76215976Sjmallett sd $11, 88(sp) 77215976Sjmallett sd $12, 96(sp) 78215976Sjmallett sd $13, 104(sp) 79215976Sjmallett sd $14, 112(sp) 80215976Sjmallett sd $15, 120(sp) 81215976Sjmallett sd $16, 128(sp) 82215976Sjmallett sd $17, 136(sp) 83215976Sjmallett sd $18, 144(sp) 84215976Sjmallett sd $19, 152(sp) 85215976Sjmallett sd $20, 160(sp) 86215976Sjmallett sd $21, 168(sp) 87215976Sjmallett sd $22, 176(sp) 88215976Sjmallett sd $23, 184(sp) 89215976Sjmallett sd $24, 192(sp) 90215976Sjmallett sd $25, 200(sp) 91215976Sjmallett sd $26, 208(sp) 92215976Sjmallett sd $27, 216(sp) 93215976Sjmallett mfhi k0 // Reading lo and high takes multiple cycles 94215976Sjmallett mflo k1 // Do it here so it completes by the time we need it 95215976Sjmallett sd $28, 224(sp) 96215976Sjmallett daddu $1, sp, STACK_SIZE // Correct the SP for the space we used 97215976Sjmallett sd $1, 232(sp) 98215976Sjmallett sd $30, 240(sp) 99215976Sjmallett sd $31, 248(sp) // saved all general purpose registers 100215976Sjmallett sd k0, 256(sp) // save hi 101215976Sjmallett sd k1, 264(sp) // save lo 102215976Sjmallett /* Save DCACHE error register early, since any non-errored DCACHE accesses will clear 103215976Sjmallett ** error bit */ 104215976Sjmallett dmfc0 k0, $27, 1 105215976Sjmallett sd k0, 272(sp) 106232812Sjmallett /* Store EPC for GCC's frame unwinder. */ 107215976Sjmallett dmfc0 k0, $14 108215976Sjmallett sd k0, 280(sp) 109215976Sjmallett 110215976Sjmallett dla k0, cvmx_interrupt_in_isr 111215976Sjmallett li k1, 1 112215976Sjmallett sw k1, 0(k0) 113215976Sjmallett 114215976Sjmallett dla k0, cvmx_interrupt_do_irq 115215976Sjmallett jal k0 116215976Sjmallett dadd a0, sp, 0 // First argument is array of registers 117215976Sjmallett 118215976Sjmallett dla k0, cvmx_interrupt_in_isr 119215976Sjmallett sw $0, 0(k0) 120215976Sjmallett 121215976Sjmallett ld k0, 256(sp) // read hi 122215976Sjmallett ld k1, 264(sp) // read lo 123215976Sjmallett mthi k0 // restore hi 124215976Sjmallett mtlo k1 // restore lo 125215976Sjmallett 126215976Sjmallett ld $1, 8(sp) // start restoring registers 127215976Sjmallett ld $2, 16(sp) 128215976Sjmallett ld $3, 24(sp) 129215976Sjmallett ld $4, 32(sp) 130215976Sjmallett ld $5, 40(sp) 131215976Sjmallett ld $6, 48(sp) 132215976Sjmallett ld $7, 56(sp) 133215976Sjmallett ld $8, 64(sp) 134215976Sjmallett ld $9, 72(sp) 135215976Sjmallett ld $10, 80(sp) 136215976Sjmallett ld $11, 88(sp) 137215976Sjmallett ld $12, 96(sp) 138215976Sjmallett ld $13, 104(sp) 139215976Sjmallett ld $14, 112(sp) 140215976Sjmallett ld $15, 120(sp) 141215976Sjmallett ld $16, 128(sp) 142215976Sjmallett ld $17, 136(sp) 143215976Sjmallett ld $18, 144(sp) 144215976Sjmallett ld $19, 152(sp) 145215976Sjmallett ld $20, 160(sp) 146215976Sjmallett ld $21, 168(sp) 147215976Sjmallett ld $22, 176(sp) 148215976Sjmallett ld $23, 184(sp) 149215976Sjmallett ld $24, 192(sp) 150215976Sjmallett ld $25, 200(sp) 151215976Sjmallett ld $26, 208(sp) 152215976Sjmallett ld $28, 224(sp) 153215976Sjmallett ld $30, 240(sp) 154215976Sjmallett ld $31, 248(sp) // restored all general purpose registers 155215976Sjmallett ld $29, 232(sp) // No need to correct for STACK_SIZE 156215976Sjmallett eret 157215976Sjmallett nop 158215976SjmallettEND(cvmx_interrupt_stage2) 159215976Sjmallett 160215976Sjmallett// Icache and Dcache exception handler. This code is executed 161215976Sjmallett// with ERL set so we can't us virtual addresses. We save and restore 162215976Sjmallett// K0 to a global memory location so we can handle cache errors from exception 163215976Sjmallett// context. This means that if two cores get a cache exception at the same time 164215976Sjmallett// the K0 might be corrupted. This entire handler MUST fit in 128 bytes. 165215976Sjmallett#define K0_STORE_LOCATION 8 166215976Sjmallett#define DCACHE_ERROR_COUNT 16 167215976Sjmallett#define ICACHE_ERROR_COUNT 24 168215976SjmallettLEAF(cvmx_interrupt_cache_error) 169215976Sjmallett .set push 170215976Sjmallett .set noreorder 171215976Sjmallett sd k0, K0_STORE_LOCATION($0) // Store K0 into global loc in case we're in an exception 172215976Sjmallett dmfc0 k0, $27, 1 // Get Dcache error status before any loads 173215976Sjmallett bbit0 k0, 0, not_dcache_error // Skip dcache count if no error 174215976Sjmallett dmtc0 k0, $27, 1 // Clear any Dcache errors 175215976Sjmallett ld k0, DCACHE_ERROR_COUNT($0) // Load the dcache error count 176215976Sjmallett daddu k0, 1 // Increment the dcache error count 177215976Sjmallett sd k0, DCACHE_ERROR_COUNT($0) // Store the dcache error count 178215976Sjmallettnot_dcache_error: 179215976Sjmallett dmfc0 k0, $27, 0 // Get the Icache error status 180215976Sjmallett bbit0 k0, 0, not_icache_error // Skip Icache count if no error 181215976Sjmallett dmtc0 k0, $27, 0 // Clear any Icache errors 182215976Sjmallett ld k0, ICACHE_ERROR_COUNT($0) // Load the icache error count 183215976Sjmallett daddu k0, 1 // Increment the icache error count 184215976Sjmallett sd k0, ICACHE_ERROR_COUNT($0) // Store the icache error count 185215976Sjmallettnot_icache_error: 186215976Sjmallett ld k0, K0_STORE_LOCATION($0) // Restore K0 since we might have been in an exception 187232812Sjmallett nop 188232812Sjmallett nop 189232812Sjmallett nop 190232812Sjmallett nop 191232812Sjmallett nop 192232812Sjmallett nop // Keep the ERET 8 instructions away 193232812Sjmallett nop // from a branch target. 194215976Sjmallett eret // Return from the Icache exception 195215976Sjmallett .set pop 196215976SjmallettEND(cvmx_interrupt_cache_error) 197215976Sjmallett 198