os/kernelhwsrv/kernel/eka/nkern/x86/vectors.cpp
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
     1 // Copyright (c) 1998-2009 Nokia Corporation and/or its subsidiary(-ies).
     2 // All rights reserved.
     3 // This component and the accompanying materials are made available
     4 // under the terms of the License "Eclipse Public License v1.0"
     5 // which accompanies this distribution, and is available
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
     7 //
     8 // Initial Contributors:
     9 // Nokia Corporation - initial contribution.
    10 //
    11 // Contributors:
    12 //
    13 // Description:
    14 // e32\nkern\x86\vectors.cpp
    15 // 
    16 //
    17 
    18 // NThreadBase member data
    19 #define __INCLUDE_NTHREADBASE_DEFINES__
    20 
    21 #include <x86.h>
    22 #include "vectors.h"
    23 
    24 #ifdef _DEBUG
    25 #define __CHECK_LOCK_STATE__
    26 #endif
    27 
    28 void __X86VectorIrq();
    29 void __X86VectorExc();
    30 void __X86ExcFault(TAny*);
    31 
    32 
    33 /** Register the global IRQ handler
    34 	Called by the base port at boot time to bind the top level IRQ dispatcher
    35 	to the X86 common IRQ handler. Should not be called at any other time.
    36 
    37 	The handler specified will be called with IRQs disabled. ESP will point
    38 	to the top of the interrupt stack. On entry to the handler EAX will point
    39 	to a block of saved registers, as follows:
    40 
    41 	[EAX+00h] = saved EDX
    42 	[EAX+04h] = saved ECX
    43 	[EAX+08h] = saved EAX
    44 	[EAX+0Ch] = saved ES
    45 	[EAX+10h] = saved DS
    46 	[EAX+14h] = interrupt vector number
    47 	[EAX+18h] = return EIP
    48 	[EAX+1Ch] = return CS
    49 	[EAX+20h] = return EFLAGS
    50 	[EAX+24h] = return ESP if interrupt occurred while CPL>0
    51 	[EAX+28h] = return SS if interrupt occurred while CPL>0
    52 
    53 	The handler should preserve all registers other than EAX, ECX, EDX
    54 	and should return using a standard RET instruction.
    55 
    56 	@param	aHandler The address of the top level IRQ dispatcher routine
    57  */
    58 EXPORT_C void X86::SetIrqHandler(TLinAddr aHandler)
    59 	{
    60 	X86_IrqHandler=aHandler;
    61 	}
    62 
    63 
    64 /** Return the address immediately after the end of the interrupt stack.
    65 
    66 	@return Interrupt Stack Base + Interrupt Stack Size
    67  */
    68 EXPORT_C TLinAddr X86::IrqStackTop(TInt /*aCpu*/)
    69 	{
    70 	return TLinAddr(X86_IrqStack) + IRQ_STACK_SIZE;
    71 	}
    72 
    73 
    74 void SetTrapGate(SX86Des* aEntry, PFV aHandler, TInt aDPL)
    75 	{
    76 	aEntry->iLow=(KRing0CS<<16)|(TUint32(aHandler)&0xffff);
    77 	aEntry->iHigh=(TUint32(aHandler)&0xffff0000) | 0x8f00 | (aDPL<<13);
    78 	}
    79 
    80 void SetInterruptGate(SX86Des* aEntry, PFV aHandler, TInt aDPL)
    81 	{
    82 	aEntry->iLow=(KRing0CS<<16)|(TUint32(aHandler)&0xffff);
    83 	aEntry->iHigh=(TUint32(aHandler)&0xffff0000) | 0x8e00 | (aDPL<<13);
    84 	}
    85 
    86 void SetTssDescriptor(SX86Des* aEntry, TX86Tss* aTss)
    87 	{
    88 	TUint addr3=TUint(aTss)>>24;
    89 	TUint addr2=(TUint(aTss)>>16)&0xff;
    90 	TUint addr01=TUint(aTss)&0xffff;
    91 	aEntry->iLow=(addr01<<16)|(sizeof(TX86Tss)-1);
    92 	aEntry->iHigh=(addr3<<24)|0x00108900|addr2;
    93 	}
    94 
    95 void X86::Init1Interrupts()
    96 //
    97 // Initialise the interrupt and exception vector handlers.
    98 //
    99 	{
   100 //	TheIrqHandler=0;	// done by placing TheIrqHandler, TheFiqHandler in .bss
   101 	__KTRACE_OPT(KBOOT,DEBUGPRINT(">X86::Init1Interrupts()"));
   102 	memset(X86_IrqStack,0xaa,IRQ_STACK_SIZE);
   103 
   104 #ifndef __STANDALONE_NANOKERNEL__
   105 	TStackInfo& stackInfo =  TheSuperPage().iStackInfo;
   106 	stackInfo.iIrqStackBase = X86_IrqStack;
   107 	stackInfo.iIrqStackSize = IRQ_STACK_SIZE;
   108 #endif
   109 	
   110 	TCpuPage& cp=X86::CpuPage();
   111 	memclr(cp.iIdt, KIdtSize*sizeof(SX86Des));
   112 	TInt i;
   113 	for (i=0; i<64; i++)
   114 		{
   115 		if (i==0x03 || i==0x20 || i==0x21)
   116 			SetTrapGate(cp.iIdt+i, TheExcVectors[i], 3);
   117 		else if (i<0x20)
   118 			SetTrapGate(cp.iIdt+i, TheExcVectors[i], 0);
   119 		if (i>=0x30)
   120 			SetInterruptGate(cp.iIdt+i, TheExcVectors[i], 0);
   121 		}
   122 	X86_IrqNestCount=-1;
   123 	X86::DefaultCR0=get_cr0();
   124 	memclr(&cp.iTss,sizeof(TX86Tss));
   125 	cp.iTss.iCR3=get_cr3();
   126 	cp.iTss.iSs0=KRing0DS;
   127 	cp.iTss.iEsp0=get_esp();
   128 	SetTssDescriptor(&cp.iGdt[5],&cp.iTss);
   129 	X86_TSS_Ptr=&cp.iTss;
   130 	__lidt(cp.iIdt,KIdtSize);
   131 	__KTRACE_OPT(KBOOT,DEBUGPRINT("<X86::Init1Interrupts()"));
   132 	}
   133 
   134 
   135 /**	Return the current processor context type (thread, IDFC or interrupt)
   136 
   137 	@return	A value from NKern::TContext enumeration (but never EEscaped)
   138 	@pre	Any context
   139 
   140 	@see	NKern::TContext
   141  */
   142 EXPORT_C TInt NKern::CurrentContext()
   143 	{
   144 	if (X86_IrqNestCount >= 0)
   145 		return NKern::EInterrupt;
   146 	if (TheScheduler.iInIDFC)
   147 		return NKern::EIDFC;
   148 	return NKern::EThread;
   149 	}
   150 
   151 extern "C" void ExcFault(TAny*);
   152 void __X86ExcFault(TAny* aInfo)
   153 	{
   154 	ExcFault(aInfo);
   155 	}
   156