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