Windows2000/private/ntos/ke/mips/buserror.c

310 lines
7.0 KiB
C
Raw Normal View History

2001-01-01 00:00:00 +01:00
/*++
Copyright (c) 1991 Microsoft Corporation
Module Name:
buserror.c
Abstract:
This module implements the code necessary to process data and instruction
bus errors and to set the address of the cache error routine.
Author:
David N. Cutler (davec) 31-Oct-1991
Environment:
Kernel mode only.
Revision History:
--*/
#include "ki.h"
BOOLEAN
KeBusError (
IN PEXCEPTION_RECORD ExceptionRecord,
IN PKEXCEPTION_FRAME ExceptionFrame,
IN PKTRAP_FRAME TrapFrame,
IN PVOID VirtualAddress,
IN PHYSICAL_ADDRESS PhysicalAddress
)
/*++
Routine Description:
This function provides the default bus error handling routine for NT.
N.B. There is no return from this routine.
Arguments:
ExceptionRecord - Supplies a pointer to an exception record.
ExceptionFrame - Supplies a pointer to an exception frame.
TrapFrame - Supplies a pointer to a trap frame.
VirtualAddress - Supplies the virtual address of the bus error.
PhysicalAddress - Supplies the physical address of the bus error.
Return Value:
None.
--*/
{
// Bug check specifying the exception code, the virtual address, the
// low part of the physical address, the current processor state, and
// the exception PC.
KeBugCheckEx(ExceptionRecord->ExceptionCode & 0xffff,
(ULONG)VirtualAddress,
PhysicalAddress.LowPart,
TrapFrame->Psr,
TrapFrame->Fir);
return FALSE;
}
PHYSICAL_ADDRESS
KiGetPhysicalAddress (
IN PVOID VirtualAddress
)
/*++
Routine Description:
This function computes the physical address for a given virtual address.
Arguments:
VirtualAddress - Supplies the virtual address whose physical address is
to be computed.
Return Value:
The physical address that correcponds to the specified virtual address.
--*/
{
PHYSICAL_ADDRESS PhysicalAddress;
// If the address is a KSEG0 or KSEG1 address, then mask off the high
// three address bits and return the result as the physical address.
// Otherwise, call memory management to convert the virtual address to
// a physical address.
if (((ULONG)VirtualAddress >= KSEG0_BASE) &&
((ULONG)VirtualAddress < (KSEG1_BASE + 0x20000000))) {
PhysicalAddress.LowPart = (ULONG)VirtualAddress & 0x1fffffff;
PhysicalAddress.HighPart = 0;
return PhysicalAddress;
} else {
return MmGetPhysicalAddress(VirtualAddress);
}
}
VOID
KiDataBusError (
IN PEXCEPTION_RECORD ExceptionRecord,
IN PKEXCEPTION_FRAME ExceptionFrame,
IN PKTRAP_FRAME TrapFrame
)
/*++
Routine Description:
This function is called to process a data bus error. The virtual and
physical address of the error are computed and the data bus error
processing routine is called indirectly through the PCR. NT provides
a standard routine to process the error and shutdown the system. A
vendor, however, can replace the standard NT routine and do additional
processing if necessary via the HAL.
N.B. There is no return from this routine.
Arguments:
ExceptionRecord - Supplies a pointer to an exception record.
ExceptionFrame - Supplies a pointer to an exception frame.
TrapFrame - Supplies a pointer to a trap frame.
Return Value:
None.
--*/
{
PVOID VirtualAddress;
PHYSICAL_ADDRESS PhysicalAddress;
MIPS_INSTRUCTION FaultInstruction;
// Any exception that occurs during the attempted calculation of the
// virtual address causes the virtual address calculation to be
// aborted and the virtual address of the instruction itself is used
// instead.
try {
// Compute the effective address of the reference.
FaultInstruction.Long = *((PULONG)ExceptionRecord->ExceptionAddress);
VirtualAddress = (PVOID)(KiGetRegisterValue(FaultInstruction.i_format.Rs,
ExceptionFrame,
TrapFrame) +
FaultInstruction.i_format.Simmediate);
// If an exception occurs, then abort the calculation of the virtual
// address and set the virtual address equal to the instruction address.
} except (EXCEPTION_EXECUTE_HANDLER) {
VirtualAddress = ExceptionRecord->ExceptionAddress;
}
// Compute the physical address that corresponds to the data address.
PhysicalAddress = KiGetPhysicalAddress(VirtualAddress);
// If a value of FALSE is returned by the data bus error handling routine,
// then bug check. Otherwise, assume that the error has been handled and
// return.
if ((PCR->DataBusError)(ExceptionRecord,
ExceptionFrame,
TrapFrame,
VirtualAddress,
PhysicalAddress) == FALSE) {
KeBugCheck(DATA_BUS_ERROR);
}
return;
}
VOID
KiInstructionBusError (
IN PEXCEPTION_RECORD ExceptionRecord,
IN PKEXCEPTION_FRAME ExceptionFrame,
IN PKTRAP_FRAME TrapFrame
)
/*++
Routine Description:
This function is called to process an instruction bus error. The virtual
and physical address of the error are computed and the instruction bus
error processing routine is called indirectly through the PCR. NT provides
a standard routine to process the error and shutdown the system. A vendor,
however, can replace the standard NT routine and do additional processing
if necessary via the HAL.
N.B. There is no return from this routine.
Arguments:
ExceptionRecord - Supplies a pointer to an exception record.
ExceptionFrame - Supplies a pointer to an exception frame.
TrapFrame - Supplies a pointer to a trap frame.
Return Value:
None.
--*/
{
PVOID VirtualAddress;
PHYSICAL_ADDRESS PhysicalAddress;
// Compute the physical address that corresponds to the data address.
VirtualAddress = ExceptionRecord->ExceptionAddress;
PhysicalAddress = KiGetPhysicalAddress(VirtualAddress);
// If a value of FALSE is returned by the instructiona bus error handling
// routine, then bug check. Otherwise, assume that the error has been
// handled and return.
if ((PCR->InstructionBusError)(ExceptionRecord,
ExceptionFrame,
TrapFrame,
VirtualAddress,
PhysicalAddress) == FALSE) {
KeBugCheck(INSTRUCTION_BUS_ERROR);
}
return;
}
VOID
KeSetCacheErrorRoutine (
IN PKCACHE_ERROR_ROUTINE Routine
)
/*++
Routine Description:
This function is called to set the address of the cache error routine.
The cache error routine is called whenever a cache error occurs.
Arguments:
Routine - Supplies a pointer to the cache error routine.
Return Value:
None.
--*/
{
// Set the address of the cache error routine.
*((PULONG)CACHE_ERROR_VECTOR) = (ULONG)Routine | KSEG1_BASE;
return;
}