|
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 |