// ========== Copyright Header Begin ==========================================
// OpenSPARC T2 Processor File: N2_IrfEcc.cc
// Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved.
// DO NOT ALTER OR REMOVE COPYRIGHT NOTICES.
// The above named 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.
// The above named program is distributed in the hope that it will be
// useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// General Public License for more details.
// You should have received a copy of the GNU General Public
// License along with this work; if not, write to the Free Software
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
// ========== Copyright Header End ============================================
/************************************************************************
** Copyright (C) 2006, Sun Microsystems, Inc.
** Sun considers its source code as an unpublished, proprietary
** trade secret and it is available only under strict license provisions.
** This copyright notice is placed here only to protect Sun in the event
** the source is deemed a published work. Disassembly, decompilation,
** or other means of reducing the object code to human readable form
** is prohibited by the license agreement under which this code is
** provided to the user or company in possession of this copy.
*************************************************************************/
#include "BL_Hamming_64_8_Synd.h"
extern "C" SS_Vaddr
n2_irf_ras_inject(SS_Vaddr pc
,
assert (reg_nr
>= 0 && reg_nr
< 32);
N2_Strand
* n2_strand
= (N2_Strand
*)s
;
N2_Core
& n2_core
= n2_strand
->core
;
unsigned long long value
= n2_strand
->get_irf(SS_Strand::reg_idx2off(reg_nr
));
BL_EccBits ecc_obj
= BL_Hamming_64_8_Synd::calc_check_bits(value
);
unsigned ecc
= ecc_obj
.get();
if ((n2_core
.error_inject
.ene() == 1) && (n2_core
.error_inject
.ircu() == 1))
ecc
^= n2_core
.error_inject
.eccmask();
// Set back the corrputed ecc
n2_strand
->irf_ecc
[reg_nr
] = ecc_obj
;
return 0; // Not sure if this is the right value to return
// This method detects any errors (injected or otherwise), associtated
// with this particular register in IRF
extern "C" SS_Vaddr
n2_irf_ras_detect(SS_Vaddr pc
,
assert (reg_nr
>= 0 && reg_nr
< 32);
N2_Strand
* n2_strand
= (N2_Strand
*)s
;
N2_Core
& n2_core
= n2_strand
->core
;
// Error Detection happens only if the IRF bit in CERER is set
unsigned long long value
= n2_strand
->get_irf(SS_Strand::reg_idx2off(reg_nr
));
BL_EccBits ecc_obj
= n2_strand
->irf_ecc
[reg_nr
];
// Check if the ecc associated with this register is a valid ecc
// Syndrome is the difference between the stored and calculated ECC values
BL_Hamming_64_8_Synd syndrome
= BL_Hamming_64_8_Synd(value
,ecc_obj
);
// Setting the current global level
unsigned long long gl
= 0; // Dummy value... need to get actual val
unsigned long long temp_reg
= reg_nr
;
// If the syndrome is not zero, then it means an ECC error has occured
// Errors are recorded only if the PSCCE bit is set in the SETER
if (n2_strand
->seter
.pscce())
if (syndrome
.isSingleBitError())
n2_strand
->data_sfsr
.error_type(2);
else if (syndrome
.isDoubleBitError() || syndrome
.isMultipleBitError())
n2_strand
->data_sfsr
.error_type(1);
unsigned long long native_add
= 0;
// Based on N2 PRM, the syndrome should be recorded
// in bits 14:7 of DSFAR (fault address register)
unsigned long long intermediate_err_add
= (native_add
& ~0x7f80ULL
) |
syndrome
.getSyndrome() << 7;
// Capture global level in bits 6:5
unsigned long long intermediate1_err_add
= (intermediate_err_add
& ~0x60ULL
) |
// capture the register number in bits 4:0
unsigned long long error_add
= (intermediate1_err_add
& ~0x1fULL
) | temp_reg
;
n2_strand
->data_sfar
.error_addr(error_add
);
return (s
->trap
)(pc
,npc
,s
,i
,SS_Trap::INTERNAL_PROCESSOR_ERROR
);
// If the ecc associated with the register is invalid
// Not sure what the exact functioning should be in this case
// Should we calculate clean ecc and associate it with this reg (as in Riesling)
// unsigned ecc = N2_EccFile::calc_n2_IRF_checks(value);
// Or should the program just call it quits!
// cerr << " Invalid ECC: Aborting!" << endl;