author | Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com> |
Tue, 31 Aug 2010 16:34:26 +0300 | |
branch | RCL_3 |
changeset 43 | c1f20ce4abcf |
parent 0 | a41df078684a |
child 44 | 3e88ff8f41d5 |
permissions | -rw-r--r-- |
0 | 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) |
|
43
c1f20ce4abcf
Revision: 201035
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
89 |
a = TLinAddr(TheSubSchedulers[aCpu].iSSX.iIrqStackTop); |
0 | 90 |
else |
91 |
{ |
|
92 |
TInt irq = NKern::DisableAllInterrupts(); |
|
43
c1f20ce4abcf
Revision: 201035
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
93 |
a = TLinAddr(SubScheduler().iSSX.iIrqStackTop); |
0 | 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]; |
|
43
c1f20ce4abcf
Revision: 201035
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
153 |
ss.iSSX.iIrqNestCount = (TLinAddr)(-1); |
c1f20ce4abcf
Revision: 201035
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
154 |
ss.iSSX.iIrqStackTop = (TLinAddr)esp; |
c1f20ce4abcf
Revision: 201035
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
155 |
ss.iSSX.iTss = &cd.iTss; |
0 | 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 |