kernel/eka/nkernsmp/x86/vectors.cpp
changeset 0 a41df078684a
child 43 c1f20ce4abcf
equal deleted inserted replaced
-1:000000000000 0:a41df078684a
       
     1 // Copyright (c) 2006-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\nkernsmp\x86\vectors.cpp
       
    15 // 
       
    16 //
       
    17 
       
    18 #include <x86.h>
       
    19 #include <apic.h>
       
    20 #include <nk_irq.h>
       
    21 #include "vectors.h"
       
    22 
       
    23 TUint32 __tr();
       
    24 void __ltr(TInt);
       
    25 
       
    26 extern "C" void _irqdebug(TUint a)
       
    27 	{
       
    28 	if (a>=0x30)
       
    29 		return;
       
    30 	__KTRACE_OPT(KSCHED2,DEBUGPRINT("!%02x",a));
       
    31 	}
       
    32 
       
    33 extern "C" void IrqStartTrace(TUint32 aVector)
       
    34 	{
       
    35 	__ACQUIRE_BTRACE_LOCK();
       
    36 	BTraceData.iHandler(BTRACE_HEADER(8,BTrace::ECpuUsage,BTrace::EIrqStart),0,0,aVector,0,0,0,0);
       
    37 	__RELEASE_BTRACE_LOCK();
       
    38 	}
       
    39 
       
    40 extern "C" void IrqEndTrace()
       
    41 	{
       
    42 	__ACQUIRE_BTRACE_LOCK();
       
    43 	BTraceData.iHandler(BTRACE_HEADER(4,BTrace::ECpuUsage,BTrace::EIrqEnd),0,0,0,0,0,0,0);
       
    44 	__RELEASE_BTRACE_LOCK();
       
    45 	}
       
    46 
       
    47 
       
    48 /** Register the global IRQ handler
       
    49 	Called by the base port at boot time to bind the top level IRQ dispatcher
       
    50 	to the X86 common IRQ handler. Should not be called at any other time.
       
    51 
       
    52 	The handler specified will be called with IRQs disabled. ESP will point
       
    53 	to the top of the interrupt stack. On entry to the handler EAX will point
       
    54 	to a block of saved registers, as follows:
       
    55 
       
    56 	[EAX+00h] = saved ESI
       
    57 	[EAX+04h] = saved EDI
       
    58 	[EAX+08h] = saved EDX
       
    59 	[EAX+0Ch] = saved ECX
       
    60 	[EAX+10h] = saved EAX
       
    61 	[EAX+14h] = saved ES
       
    62 	[EAX+18h] = saved DS
       
    63 	[EAX+1Ch] = interrupt vector number
       
    64 	[EAX+20h] = return EIP
       
    65 	[EAX+24h] = return CS
       
    66 	[EAX+28h] = return EFLAGS
       
    67 	[EAX+2Ch] = return ESP if interrupt occurred while CPL>0
       
    68 	[EAX+30h] = return SS if interrupt occurred while CPL>0
       
    69 
       
    70 	The handler should preserve all registers other than EAX, ECX, EDX
       
    71 	and should return using a standard RET instruction.
       
    72 
       
    73 	@param	aHandler The address of the top level IRQ dispatcher routine
       
    74  */
       
    75 EXPORT_C void X86::SetIrqHandler(TLinAddr aHandler)
       
    76 	{
       
    77 	X86_IrqHandler = aHandler;
       
    78 	}
       
    79 
       
    80 
       
    81 /** Return the address immediately after the end of the interrupt stack.
       
    82 
       
    83 	@return Interrupt Stack Base + Interrupt Stack Size
       
    84  */
       
    85 EXPORT_C TLinAddr X86::IrqStackTop(TInt aCpu)
       
    86 	{
       
    87 	TLinAddr a = 0;
       
    88 	if (aCpu>=0 && aCpu<KMaxCpus)
       
    89 		a = TLinAddr(TheSubSchedulers[aCpu].i_IrqStackTop);
       
    90 	else
       
    91 		{
       
    92 		TInt irq = NKern::DisableAllInterrupts();
       
    93 		a = TLinAddr(SubScheduler().i_IrqStackTop);
       
    94 		NKern::RestoreInterrupts(irq);
       
    95 		}
       
    96 	return a;
       
    97 	}
       
    98 
       
    99 void SetTrapGate(SX86Des* aEntry, PFV aHandler, TInt aDPL)
       
   100 	{
       
   101 	aEntry->iLow=(KRing0CS<<16)|(TUint32(aHandler)&0xffff);
       
   102 	aEntry->iHigh=(TUint32(aHandler)&0xffff0000) | 0x8f00 | (aDPL<<13);
       
   103 	}
       
   104 
       
   105 void SetInterruptGate(SX86Des* aEntry, PFV aHandler, TInt aDPL)
       
   106 	{
       
   107 	aEntry->iLow=(KRing0CS<<16)|(TUint32(aHandler)&0xffff);
       
   108 	aEntry->iHigh=(TUint32(aHandler)&0xffff0000) | 0x8e00 | (aDPL<<13);
       
   109 	}
       
   110 
       
   111 void SetTssDescriptor(SX86Des* aEntry, TX86Tss* aTss)
       
   112 	{
       
   113 	TUint addr3=TUint(aTss)>>24;
       
   114 	TUint addr2=(TUint(aTss)>>16)&0xff;
       
   115 	TUint addr01=TUint(aTss)&0xffff;
       
   116 	aEntry->iLow=(addr01<<16)|(sizeof(TX86Tss)-1);
       
   117 	aEntry->iHigh=(addr3<<24)|0x00108900|addr2;
       
   118 	}
       
   119 
       
   120 void X86::Init1Interrupts()
       
   121 //
       
   122 // Initialise the interrupt and exception vector handlers.
       
   123 //
       
   124 	{
       
   125 //	TheIrqHandler=0;	// done by placing TheIrqHandler, TheFiqHandler in .bss
       
   126 	__KTRACE_OPT(KBOOT,DEBUGPRINT(">X86::Init1Interrupts()"));
       
   127 
       
   128 	TCpuPages& cp=X86::CpuPage();
       
   129 	memclr(cp.iIdt, KIdtSize*sizeof(SX86Des));
       
   130 	TInt i;
       
   131 	for (i=0; i<(TInt)(sizeof(TheExcVectors)/sizeof(PFV)); i++)
       
   132 		{
       
   133 		if (i==0x03 || i==0x20 || i==0x21)
       
   134 			SetInterruptGate(cp.iIdt+i, TheExcVectors[i], 3);
       
   135 		else if (i<0x20 && i!=0x02)
       
   136 			SetInterruptGate(cp.iIdt+i, TheExcVectors[i], 0);
       
   137 		if (i==0x02 || i>=0x27)
       
   138 			SetInterruptGate(cp.iIdt+i, TheExcVectors[i], 0);
       
   139 		}
       
   140 	for (i=0; i<KMaxCpus; ++i)
       
   141 		{
       
   142 		SCpuData& cd = cp.iCpuData[i];
       
   143 		memclr(&cd, sizeof(cd) - sizeof(cd.iIrqStack));
       
   144 		memset(cd.iIrqStack, 0xab+i*2, sizeof(cd.iIrqStack));
       
   145 
       
   146 		TUint32 esp = (TUint32)cd.iIrqStack + sizeof(cd.iIrqStack);
       
   147 		cd.iTss.iCR3 = get_cr3();
       
   148 		cd.iTss.iSs0 = KRing0DS;
       
   149 		cd.iTss.iEsp0 = esp;
       
   150 		SetTssDescriptor(&cp.iGdt[5+i], &cd.iTss);
       
   151 
       
   152 		TSubScheduler& ss = TheSubSchedulers[i];
       
   153 		ss.i_IrqNestCount = (TAny*)(-1);
       
   154 		ss.i_IrqStackTop = (TAny*)esp;
       
   155 		ss.i_Tss = &cd.iTss;
       
   156 		}
       
   157 
       
   158 	X86::DefaultCR0 = get_cr0();
       
   159 	NIrq::HwInit1();
       
   160 
       
   161 	__ltr(TSS_SELECTOR(0));
       
   162 	__lidt(cp.iIdt, KIdtSize);
       
   163 	__KTRACE_OPT(KBOOT,DEBUGPRINT("<X86::Init1Interrupts()"));
       
   164 	}
       
   165 
       
   166 
       
   167 extern "C" void ExcFault(TAny*);
       
   168 void __X86ExcFault(TAny* aInfo)
       
   169 	{
       
   170 	ExcFault(aInfo);
       
   171 	}
       
   172