ReactOS 0.4.16-dev-329-g9223134
apic.c File Reference
#include <hal.h>
#include <halfuncs.h>
#include <rtlfuncs.h>
#include <debug.h>
Include dependency graph for apic.c:

Go to the source code of this file.

Macros

#define NDEBUG
 
#define BIOS_AREA   0x0
 
#define COMMON_AREA   0x2000
 
#define HZ   (100)
 
#define APIC_DIVISOR   (16)
 
#define CMOS_READ(address)
 
#define CMOS_WRITE(address, value)
 

Functions

ULONG Read8254Timer (VOID)
 
VOID WaitFor8254Wraparound (VOID)
 
VOID MpsTimerInterrupt (VOID)
 
VOID MpsErrorInterrupt (VOID)
 
VOID MpsSpuriousInterrupt (VOID)
 
VOID MpsIpiInterrupt (VOID)
 
ULONG APICGetMaxLVT (VOID)
 
VOID APICClear (VOID)
 
VOID EnableApicMode (VOID)
 
__inline VOID DisableSMPMode (VOID)
 
VOID DumpESR (VOID)
 
VOID APICDisable (VOID)
 
static VOID APICDumpBit (ULONG base)
 
VOID APICDump (VOID)
 
BOOLEAN VerifyLocalAPIC (VOID)
 
VOID APICSetup (VOID)
 
VOID MpsErrorHandler (VOID)
 
VOID MpsSpuriousHandler (VOID)
 
VOID MpsIRQTrapFrameToTrapFrame (PKIRQ_TRAPFRAME IrqTrapFrame, PKTRAP_FRAME TrapFrame)
 
VOID MpsTimerHandler (ULONG Vector, PKIRQ_TRAPFRAME Trapframe)
 
VOID APICSetupLVTT (ULONG ClockTicks)
 
VOID APICCalibrateTimer (ULONG CPU)
 
VOID SetInterruptGate (ULONG index, ULONG_PTR address)
 
VOID HaliInitBSP (VOID)
 
VOID FASTCALL DECLSPEC_NORETURN HalpApcInterruptHandler (IN PKTRAP_FRAME TrapFrame)
 

Variables

ULONG CPUCount
 
ULONG BootCPU
 
ULONG OnlineCPUs
 
CPU_INFO CPUMap [MAX_CPU]
 
PULONG APICBase = (PULONG)APIC_DEFAULT_BASE
 
ULONG APICMode
 
ULONG lastregr [MAX_CPU]
 
ULONG lastvalr [MAX_CPU]
 
ULONG lastregw [MAX_CPU]
 
ULONG lastvalw [MAX_CPU]
 
CHARAPstart
 
CHARAPend
 
ULONG_PTR KernelBase
 

Macro Definition Documentation

◆ APIC_DIVISOR

#define APIC_DIVISOR   (16)

Definition at line 76 of file apic.c.

◆ BIOS_AREA

#define BIOS_AREA   0x0

Definition at line 72 of file apic.c.

◆ CMOS_READ

#define CMOS_READ (   address)
Value:
{ \
WRITE_PORT_UCHAR((PUCHAR)0x70, address)); \
READ_PORT_UCHAR((PUCHAR)0x71)); \
}
GLuint address
Definition: glext.h:9393
unsigned char * PUCHAR
Definition: typedefs.h:53

Definition at line 78 of file apic.c.

◆ CMOS_WRITE

#define CMOS_WRITE (   address,
  value 
)
Value:
{ \
WRITE_PORT_UCHAR((PUCHAR)0x70, address); \
WRITE_PORT_UCHAR((PUCHAR)0x71, value); \
}
Definition: pdh_main.c:94

Definition at line 83 of file apic.c.

◆ COMMON_AREA

#define COMMON_AREA   0x2000

Definition at line 73 of file apic.c.

◆ HZ

#define HZ   (100)

Definition at line 75 of file apic.c.

◆ NDEBUG

#define NDEBUG

Definition at line 32 of file apic.c.

Function Documentation

◆ APICCalibrateTimer()

VOID APICCalibrateTimer ( ULONG  CPU)

Definition at line 794 of file apic.c.

795{
796 ULARGE_INTEGER t1, t2;
797 LONG tt1, tt2;
798 BOOLEAN TSCPresent;
799
800 DPRINT("Calibrating APIC timer for CPU %d\n", CPU);
801
802 APICSetupLVTT(1000000000);
803
804 TSCPresent = KeGetCurrentPrcb()->FeatureBits & KF_RDTSC ? TRUE : FALSE;
805
806 /*
807 * The timer chip counts down to zero. Let's wait
808 * for a wraparound to start exact measurement:
809 * (the current tick might have been already half done)
810 */
811 //WaitFor8254Wraparound();
812
813 /*
814 * We wrapped around just now. Let's start
815 */
816 if (TSCPresent)
817 {
818 t1.QuadPart = (LONGLONG)__rdtsc();
819 }
820 tt1 = APICRead(APIC_CCRT);
821
822 //WaitFor8254Wraparound();
823
824
825 tt2 = APICRead(APIC_CCRT);
826 if (TSCPresent)
827 {
828 t2.QuadPart = (LONGLONG)__rdtsc();
829 CPUMap[CPU].CoreSpeed = (HZ * (ULONG)(t2.QuadPart - t1.QuadPart));
830 DPRINT("CPU clock speed is %ld.%04ld MHz.\n",
831 CPUMap[CPU].CoreSpeed/1000000,
832 CPUMap[CPU].CoreSpeed%1000000);
833 KeGetCurrentPrcb()->MHz = CPUMap[CPU].CoreSpeed/1000000;
834 }
835
836 CPUMap[CPU].BusSpeed = (HZ * (long)(tt1 - tt2) * APIC_DIVISOR);
837
838 /* Setup timer for normal operation */
839// APICSetupLVTT((CPUMap[CPU].BusSpeed / 1000000) * 100); // 100ns
840 APICSetupLVTT((CPUMap[CPU].BusSpeed / 1000000) * 10000); // 10ms
841// APICSetupLVTT((CPUMap[CPU].BusSpeed / 1000000) * 100000); // 100ms
842
843 DPRINT("Host bus clock speed is %ld.%04ld MHz.\n",
844 CPUMap[CPU].BusSpeed/1000000,
845 CPUMap[CPU].BusSpeed%1000000);
846}
unsigned char BOOLEAN
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
PPC_QUAL unsigned long long __rdtsc(void)
Definition: intrin_ppc.h:688
VOID APICSetupLVTT(ULONG ClockTicks)
Definition: apic.c:770
#define HZ
Definition: apic.c:75
CPU_INFO CPUMap[MAX_CPU]
Definition: apic.c:40
#define APIC_DIVISOR
Definition: apic.c:76
FORCEINLINE struct _KPRCB * KeGetCurrentPrcb(VOID)
Definition: ketypes.h:1150
#define KF_RDTSC
Definition: ketypes.h:32
long LONG
Definition: pedump.c:60
#define long
Definition: qsort.c:33
#define DPRINT
Definition: sndvol32.h:73
ULONGLONG QuadPart
Definition: ms-dtyp.idl:185
int64_t LONGLONG
Definition: typedefs.h:68
uint32_t ULONG
Definition: typedefs.h:59

Referenced by HaliInitBSP(), and HalInitializeProcessor().

◆ APICClear()

VOID APICClear ( VOID  )

Definition at line 111 of file apic.c.

112{
113 ULONG tmp, maxlvt;
114
115 maxlvt = APICGetMaxLVT();
116
117 /*
118 * Careful: we have to set masks only first to deassert
119 * any level-triggered sources.
120 */
121
122 if (maxlvt >= 3)
123 {
124 tmp = ERROR_VECTOR;
125 APICWrite(APIC_LVT3, tmp | APIC_LVT3_MASKED);
126 }
127
128 tmp = APICRead(APIC_LVTT);
129 APICWrite(APIC_LVTT, tmp | APIC_LVT_MASKED);
130
131 tmp = APICRead(APIC_LINT0);
132 APICWrite(APIC_LINT0, tmp | APIC_LVT_MASKED);
133
134 tmp = APICRead(APIC_LINT1);
135 APICWrite(APIC_LINT1, tmp | APIC_LVT_MASKED);
136
137 if (maxlvt >= 4)
138 {
139 tmp = APICRead(APIC_LVTPC);
140 APICWrite(APIC_LVTPC, tmp | APIC_LVT_MASKED);
141 }
142#if 0
143 if (maxlvt >= 5)
144 {
145 tmp = APICRead(APIC_LVTTHMR);
146 APICWrite(APIC_LVTTHMR, tmp | APIC_LVT_MASKED);
147 }
148#endif
149 /*
150 * Clean APIC state for other OSs:
151 */
152 APICWrite(APIC_LVTT, APIC_LVT_MASKED);
153 APICWrite(APIC_LINT0, APIC_LVT_MASKED);
154 APICWrite(APIC_LINT1, APIC_LVT_MASKED);
155
156 if (maxlvt >= 3)
157 {
158 APICWrite(APIC_LVT3, APIC_LVT3_MASKED);
159 }
160
161 if (maxlvt >= 4)
162 {
163 APICWrite(APIC_LVTPC, APIC_LVT_MASKED);
164 }
165#if 0
166 if (maxlvt >= 5)
167 {
168 APICWrite(APIC_LVTTHMR, APIC_LVT_MASKED);
169 }
170#endif
171}
@ APIC_LINT1
Definition: apicp.h:100
@ APIC_LINT0
Definition: apicp.h:99
ULONG APICGetMaxLVT(VOID)
Definition: apic.c:99

Referenced by APICDisable(), and EnableApicMode().

◆ APICDisable()

VOID APICDisable ( VOID  )

Definition at line 211 of file apic.c.

212{
213 ULONG tmp;
214
215 APICClear();
216
217 /*
218 * Disable APIC (implies clearing of registers for 82489DX!).
219 */
220 tmp = APICRead(APIC_SIVR);
221 tmp &= ~APIC_SIVR_ENABLE;
222 APICWrite(APIC_SIVR, tmp);
223}
@ APIC_SIVR
Definition: apicp.h:89
VOID APICClear(VOID)
Definition: apic.c:111

◆ APICDump()

VOID APICDump ( VOID  )

Definition at line 245 of file apic.c.

249{
250 ULONG v, ver, maxlvt;
251 ULONG r1, r2, w1, w2;
252 ULONG CPU = ThisCPU();
253
254
255 r1 = lastregr[CPU];
256 r2 = lastvalr[CPU];
257 w1 = lastregw[CPU];
258 w2 = lastvalw[CPU];
259
260 DbgPrint("\nPrinting local APIC contents on CPU(%d):\n", ThisCPU());
261 v = APICRead(APIC_ID);
262 DbgPrint("... ID : %08x (%01x) ", v, GET_APIC_ID(v));
263 v = APICRead(APIC_VER);
264 DbgPrint("... VERSION: %08x\n", v);
265 ver = GET_APIC_VERSION(v);
266 maxlvt = APICGetMaxLVT();
267
268 v = APICRead(APIC_TPR);
269 DbgPrint("... TPR : %08x (%02x)", v, v & ~0);
270
271 if (APIC_INTEGRATED(ver))
272 {
273 /* !82489DX */
274 v = APICRead(APIC_APR);
275 DbgPrint("... APR : %08x (%02x)\n", v, v & ~0);
276 v = APICRead(APIC_PPR);
277 DbgPrint("... PPR : %08x\n", v);
278 }
279
280 v = APICRead(APIC_EOI);
281 DbgPrint("... EOI : %08x ! ", v);
282 v = APICRead(APIC_LDR);
283 DbgPrint("... LDR : %08x\n", v);
284 v = APICRead(APIC_DFR);
285 DbgPrint("... DFR : %08x ! ", v);
286 v = APICRead(APIC_SIVR);
287 DbgPrint("... SIVR : %08x\n", v);
288
289 if (0)
290 {
291 DbgPrint("... ISR field:\n");
293 DbgPrint("... TMR field:\n");
295 DbgPrint("... IRR field:\n");
297 }
298
299 if (APIC_INTEGRATED(ver))
300 {
301 /* !82489DX */
302 if (maxlvt > 3)
303 {
304 /* Due to the Pentium erratum 3AP. */
305 APICWrite(APIC_ESR, 0);
306 }
307 v = APICRead(APIC_ESR);
308 DbgPrint("... ESR : %08x\n", v);
309 }
310
311 v = APICRead(APIC_ICR0);
312 DbgPrint("... ICR0 : %08x ! ", v);
313 v = APICRead(APIC_ICR1);
314 DbgPrint("... ICR1 : %08x ! ", v);
315
316 v = APICRead(APIC_LVTT);
317 DbgPrint("... LVTT : %08x\n", v);
318
319 if (maxlvt > 3)
320 {
321 /* PC is LVT#4. */
322 v = APICRead(APIC_LVTPC);
323 DbgPrint("... LVTPC : %08x ! ", v);
324 }
325 v = APICRead(APIC_LINT0);
326 DbgPrint("... LINT0 : %08x ! ", v);
327 v = APICRead(APIC_LINT1);
328 DbgPrint("... LINT1 : %08x\n", v);
329
330 if (maxlvt > 2)
331 {
332 v = APICRead(APIC_LVT3);
333 DbgPrint("... LVT3 : %08x\n", v);
334 }
335
336 v = APICRead(APIC_ICRT);
337 DbgPrint("... ICRT : %08x ! ", v);
338 v = APICRead(APIC_CCRT);
339 DbgPrint("... CCCT : %08x ! ", v);
340 v = APICRead(APIC_TDCR);
341 DbgPrint("... TDCR : %08x\n", v);
342 DbgPrint("\n");
343 DbgPrint("Last register read (offset): 0x%08X\n", r1);
344 DbgPrint("Last register read (value): 0x%08X\n", r2);
345 DbgPrint("Last register written (offset): 0x%08X\n", w1);
346 DbgPrint("Last register written (value): 0x%08X\n", w2);
347 DbgPrint("\n");
348}
@ APIC_PPR
Definition: apicp.h:84
@ APIC_ICR0
Definition: apicp.h:94
@ APIC_TPR
Definition: apicp.h:82
@ APIC_VER
Definition: apicp.h:81
@ APIC_LDR
Definition: apicp.h:87
@ APIC_ESR
Definition: apicp.h:93
@ APIC_IRR
Definition: apicp.h:92
@ APIC_ICR1
Definition: apicp.h:95
@ APIC_ISR
Definition: apicp.h:90
@ APIC_TDCR
Definition: apicp.h:104
@ APIC_EOI
Definition: apicp.h:85
@ APIC_ID
Definition: apicp.h:80
@ APIC_DFR
Definition: apicp.h:88
@ APIC_TMR
Definition: apicp.h:91
@ APIC_APR
Definition: apicp.h:83
const GLdouble * v
Definition: gl.h:2040
GLdouble GLdouble GLint GLint GLdouble GLdouble GLint GLint GLdouble GLdouble w2
Definition: glext.h:8308
GLdouble GLdouble GLint GLint GLdouble GLdouble GLint GLint GLdouble w1
Definition: glext.h:8308
#define DbgPrint
Definition: hal.h:12
static DNS_RECORDW r1
Definition: record.c:37
static DNS_RECORDW r2
Definition: record.c:38
ULONG lastregr[MAX_CPU]
Definition: apic.c:52
static VOID APICDumpBit(ULONG base)
Definition: apic.c:225
ULONG lastvalr[MAX_CPU]
Definition: apic.c:53
ULONG lastregw[MAX_CPU]
Definition: apic.c:54
ULONG lastvalw[MAX_CPU]
Definition: apic.c:55

Referenced by MpsErrorHandler(), and MpsSpuriousHandler().

◆ APICDumpBit()

static VOID APICDumpBit ( ULONG  base)
static

Definition at line 225 of file apic.c.

226{
227 ULONG v, i, j;
228
229 DbgPrint("0123456789abcdef0123456789abcdef\n");
230 for (i = 0; i < 8; i++)
231 {
232 v = APICRead(base + i*0x10);
233 for (j = 0; j < 32; j++)
234 {
235 if (v & (1<<j))
236 DbgPrint("1");
237 else
238 DbgPrint("0");
239 }
240 DbgPrint("\n");
241 }
242}
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint GLint GLint j
Definition: glfuncs.h:250

Referenced by APICDump().

◆ APICGetMaxLVT()

ULONG APICGetMaxLVT ( VOID  )

Definition at line 99 of file apic.c.

100{
101 ULONG tmp, ver, maxlvt;
102
103 tmp = APICRead(APIC_VER);
104 ver = GET_APIC_VERSION(tmp);
105 /* 82489DXs do not report # of LVT entries. */
106 maxlvt = APIC_INTEGRATED(ver) ? GET_APIC_MAXLVT(tmp) : 2;
107
108 return maxlvt;
109}

Referenced by APICClear(), APICDump(), APICSetup(), DumpESR(), and VerifyLocalAPIC().

◆ APICSetup()

VOID APICSetup ( VOID  )

Definition at line 482 of file apic.c.

483{
484 ULONG CPU, tmp;
485
486 CPU = ThisCPU();
487
488// APICDump();
489
490 DPRINT1("CPU%d:\n", CPU);
491 DPRINT1(" Physical APIC id: %d\n", GET_APIC_ID(APICRead(APIC_ID)));
492 DPRINT1(" Logical APIC id: %d\n", GET_APIC_LOGICAL_ID(APICRead(APIC_LDR)));
493 DPRINT1("%08x %08x %08x\n", APICRead(APIC_ID), APICRead(APIC_LDR), APICRead(APIC_DFR));
494
495 /*
496 * Intel recommends to set DFR, LDR and TPR before enabling
497 * an APIC. See e.g. "AP-388 82489DX User's Manual" (Intel
498 * document number 292116). So here it goes...
499 */
500
501 /*
502 * Put the APIC into flat delivery mode.
503 * Must be "all ones" explicitly for 82489DX.
504 */
505 APICWrite(APIC_DFR, 0xFFFFFFFF);
506
507 /*
508 * Set up the logical destination ID.
509 */
510 tmp = APICRead(APIC_LDR);
511 tmp &= ~APIC_LDR_MASK;
512 /*
513 * FIXME:
514 * This works only up to 8 CPU's
515 */
516 tmp |= (1 << (KeGetCurrentProcessorNumber() + 24));
517 APICWrite(APIC_LDR, tmp);
518
519
520 DPRINT1("CPU%d:\n", CPU);
521 DPRINT1(" Physical APIC id: %d\n", GET_APIC_ID(APICRead(APIC_ID)));
522 DPRINT1(" Logical APIC id: %d\n", GET_APIC_LOGICAL_ID(APICRead(APIC_LDR)));
523 DPRINT1("%08x %08x %08x\n", APICRead(APIC_ID), APICRead(APIC_LDR), APICRead(APIC_DFR));
524 DPRINT1("%d\n", CPUMap[CPU].APICId);
525
526 /* Accept only higher interrupts */
527 APICWrite(APIC_TPR, 0xef);
528
529 /* Enable local APIC */
530 tmp = APICRead(APIC_SIVR);
531 tmp &= ~0xff;
532 tmp |= APIC_SIVR_ENABLE;
533
534#if 0
535 tmp &= ~APIC_SIVR_FOCUS;
536#else
537 tmp |= APIC_SIVR_FOCUS;
538#endif
539
540 /* Set spurious interrupt vector */
541 tmp |= SPURIOUS_VECTOR;
542 APICWrite(APIC_SIVR, tmp);
543
544 /*
545 * Set up LVT0, LVT1:
546 *
547 * set up through-local-APIC on the BP's LINT0. This is not
548 * strictly necessery in pure symmetric-IO mode, but sometimes
549 * we delegate interrupts to the 8259A.
550 */
551 tmp = APICRead(APIC_LINT0) & APIC_LVT_MASKED;
552 if (CPU == BootCPU && (APICMode == amPIC || !tmp))
553 {
554 tmp = APIC_DM_EXTINT;
555 DPRINT1("enabled ExtINT on CPU#%d\n", CPU);
556 }
557 else
558 {
559 tmp = APIC_DM_EXTINT | APIC_LVT_MASKED;
560 DPRINT1("masked ExtINT on CPU#%d\n", CPU);
561 }
562 APICWrite(APIC_LINT0, tmp);
563
564 /*
565 * Only the BSP should see the LINT1 NMI signal, obviously.
566 */
567 if (CPU == BootCPU)
568 {
569 tmp = APIC_DM_NMI;
570 }
571 else
572 {
573 tmp = APIC_DM_NMI | APIC_LVT_MASKED;
574 }
575 if (!APIC_INTEGRATED(CPUMap[CPU].APICVersion))
576 {
577 /* 82489DX */
578 tmp |= APIC_LVT_LEVEL_TRIGGER;
579 }
580 APICWrite(APIC_LINT1, tmp);
581
582 if (APIC_INTEGRATED(CPUMap[CPU].APICVersion))
583 {
584 /* !82489DX */
585 if (APICGetMaxLVT() > 3)
586 {
587 /* Due to the Pentium erratum 3AP */
588 APICWrite(APIC_ESR, 0);
589 }
590
591 tmp = APICRead(APIC_ESR);
592 DPRINT("ESR value before enabling vector: 0x%X\n", tmp);
593
594 /* Enable sending errors */
595 tmp = ERROR_VECTOR;
596 APICWrite(APIC_LVT3, tmp);
597
598 /*
599 * Spec says clear errors after enabling vector
600 */
601 if (APICGetMaxLVT() > 3)
602 {
603 APICWrite(APIC_ESR, 0);
604 }
605 tmp = APICRead(APIC_ESR);
606 DPRINT("ESR value after enabling vector: 0x%X\n", tmp);
607 }
608}
#define DPRINT1
Definition: precomp.h:8
ULONG APICMode
Definition: apic.c:49
ULONG BootCPU
Definition: apic.c:38
FORCEINLINE ULONG KeGetCurrentProcessorNumber(VOID)
Definition: ke.h:341

Referenced by HaliInitBSP(), and HalInitializeProcessor().

◆ APICSetupLVTT()

VOID APICSetupLVTT ( ULONG  ClockTicks)

Definition at line 770 of file apic.c.

771{
772 ULONG tmp;
773
774 tmp = GET_APIC_VERSION(APICRead(APIC_VER));
775 if (!APIC_INTEGRATED(tmp))
776 {
777 tmp = SET_APIC_TIMER_BASE(APIC_TIMER_BASE_DIV) | APIC_LVT_PERIODIC | LOCAL_TIMER_VECTOR;
778 }
779 else
780 {
781 /* Periodic timer */
782 tmp = APIC_LVT_PERIODIC | LOCAL_TIMER_VECTOR;
783 }
784 APICWrite(APIC_LVTT, tmp);
785
786 tmp = APICRead(APIC_TDCR);
787 tmp &= ~(APIC_TDCR_1 | APIC_TIMER_BASE_DIV);
788 tmp |= APIC_TDCR_16;
789 APICWrite(APIC_TDCR, tmp);
790 APICWrite(APIC_ICRT, ClockTicks / APIC_DIVISOR);
791}

Referenced by APICCalibrateTimer().

◆ DisableSMPMode()

__inline VOID DisableSMPMode ( VOID  )

Definition at line 186 of file apic.c.

187{
188 /*
189 * Put the board back into PIC mode (has an effect
190 * only on certain older boards). Note that APIC
191 * interrupts, including IPIs, won't work beyond
192 * this point! The only exception are INIT IPIs.
193 */
194 WRITE_PORT_UCHAR((PUCHAR)0x22, 0x70);
195 WRITE_PORT_UCHAR((PUCHAR)0x23, 0x00);
196}
#define WRITE_PORT_UCHAR(p, d)
Definition: pc98vid.h:21

◆ DumpESR()

VOID DumpESR ( VOID  )

Definition at line 198 of file apic.c.

199{
200 ULONG tmp;
201
202 if (APICGetMaxLVT() > 3)
203 {
204 APICWrite(APIC_ESR, 0);
205 }
206 tmp = APICRead(APIC_ESR);
207 DbgPrint("ESR %08x\n", tmp);
208}

◆ EnableApicMode()

VOID EnableApicMode ( VOID  )

Definition at line 174 of file apic.c.

175{
176 /*
177 * Do not trust the local APIC being empty at bootup.
178 */
179 APICClear();
180
181 WRITE_PORT_UCHAR((PUCHAR)0x22, 0x70);
182 WRITE_PORT_UCHAR((PUCHAR)0x23, 0x01);
183}

Referenced by HaliInitBSP().

◆ HaliInitBSP()

VOID HaliInitBSP ( VOID  )

Definition at line 886 of file apic.c.

887{
888#ifdef CONFIG_SMP
889 PUSHORT ps;
890#endif
891
892 static BOOLEAN BSPInitialized = FALSE;
893
894 /* Only initialize the BSP once */
895 if (BSPInitialized)
896 {
897 ASSERT(FALSE);
898 return;
899 }
900
901 BSPInitialized = TRUE;
902
903 /* Setup interrupt handlers */
904 SetInterruptGate(LOCAL_TIMER_VECTOR, (ULONG_PTR)MpsTimerInterrupt);
907#ifdef CONFIG_SMP
909#endif
910 DPRINT("APIC is mapped at 0x%X\n", APICBase);
911
912 if (VerifyLocalAPIC())
913 {
914 DPRINT("APIC found\n");
915 }
916 else
917 {
918 DPRINT("No APIC found\n");
919 ASSERT(FALSE);
920 }
921
922 if (APICMode == amPIC)
923 {
925 }
926
927 APICSetup();
928
929#ifdef CONFIG_SMP
930 /* BIOS data segment */
931 BIOSBase = (PULONG)BIOS_AREA;
932
933 /* Area for communicating with the APs */
934 CommonBase = (PULONG)COMMON_AREA;
935
936 /* Copy bootstrap code to common area */
937 memcpy((PVOID)((ULONG_PTR)CommonBase + PAGE_SIZE),
938 &APstart,
939 (ULONG_PTR)&APend - (ULONG_PTR)&APstart + 1);
940
941 /* Set shutdown code */
942 CMOS_WRITE(0xF, 0xA);
943
944 /* Set warm reset vector */
945 ps = (PUSHORT)((ULONG_PTR)BIOSBase + 0x467);
946 *ps = (COMMON_AREA + PAGE_SIZE) & 0xF;
947
948 ps = (PUSHORT)((ULONG_PTR)BIOSBase + 0x469);
949 *ps = (COMMON_AREA + PAGE_SIZE) >> 4;
950#endif
951
952 /* Calibrate APIC timer */
954}
#define PAGE_SIZE
Definition: env_spec_w32.h:49
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
#define ASSERT(a)
Definition: mode.c:44
CHAR * APend
Definition: apic.c:70
VOID APICSetup(VOID)
Definition: apic.c:482
PULONG APICBase
Definition: apic.c:47
VOID MpsErrorInterrupt(VOID)
#define CMOS_WRITE(address, value)
Definition: apic.c:83
VOID MpsIpiInterrupt(VOID)
VOID EnableApicMode(VOID)
Definition: apic.c:174
VOID APICCalibrateTimer(ULONG CPU)
Definition: apic.c:794
#define BIOS_AREA
Definition: apic.c:72
VOID SetInterruptGate(ULONG index, ULONG_PTR address)
Definition: apic.c:849
VOID MpsSpuriousInterrupt(VOID)
VOID MpsTimerInterrupt(VOID)
CHAR * APstart
#define COMMON_AREA
Definition: apic.c:73
BOOLEAN VerifyLocalAPIC(VOID)
Definition: apic.c:350
uint32_t * PULONG
Definition: typedefs.h:59
uint16_t * PUSHORT
Definition: typedefs.h:56
uint32_t ULONG_PTR
Definition: typedefs.h:65

Referenced by HalInitializeProcessor().

◆ HalpApcInterruptHandler()

VOID FASTCALL DECLSPEC_NORETURN HalpApcInterruptHandler ( IN PKTRAP_FRAME  TrapFrame)

Definition at line 1115 of file apic.c.

1116{
1117 /* Set up a fake INT Stack */
1118 TrapFrame->EFlags = __readeflags();
1119 TrapFrame->SegCs = KGDT_R0_CODE;
1120 TrapFrame->Eip = TrapFrame->Eax;
1121
1122 /* Build the trap frame */
1123 KiEnterInterruptTrap(TrapFrame);
1124
1125 /* unimplemented */
1127
1128 /* Exit the interrupt */
1129 KiEoiHelper(TrapFrame);
1130
1131}
#define UNIMPLEMENTED
Definition: ntoskrnl.c:15
__INTRIN_INLINE uintptr_t __readeflags(void)
Definition: intrin_x86.h:1674
#define KGDT_R0_CODE
Definition: ketypes.h:123
DECLSPEC_NORETURN VOID FASTCALL KiEoiHelper(IN PKTRAP_FRAME TrapFrame)
Definition: traphdlr.c:126
FORCEINLINE VOID KiEnterInterruptTrap(IN PKTRAP_FRAME TrapFrame)
Definition: trap_x.h:368

◆ MpsErrorHandler()

VOID MpsErrorHandler ( VOID  )

Definition at line 634 of file apic.c.

635{
636 ULONG tmp1, tmp2;
637
638 APICDump();
639
640 tmp1 = APICRead(APIC_ESR);
641 APICWrite(APIC_ESR, 0);
642 tmp2 = APICRead(APIC_ESR);
643 DPRINT1("APIC error on CPU(%d) ESR(%x)(%x)\n", ThisCPU(), tmp1, tmp2);
644
645 /*
646 * Acknowledge the interrupt
647 */
648 APICSendEOI();
649
650 /* Here is what the APIC error bits mean:
651 * 0: Send CS error
652 * 1: Receive CS error
653 * 2: Send accept error
654 * 3: Receive accept error
655 * 4: Reserved
656 * 5: Send illegal vector
657 * 6: Received illegal vector
658 * 7: Illegal register address
659 */
660 DPRINT1("APIC error on CPU(%d) ESR(%x)(%x)\n", ThisCPU(), tmp1, tmp2);
661 for (;;);
662}
VOID APICDump(VOID)
Definition: apic.c:245

◆ MpsErrorInterrupt()

VOID MpsErrorInterrupt ( VOID  )

Referenced by HaliInitBSP().

◆ MpsIpiInterrupt()

VOID MpsIpiInterrupt ( VOID  )

Referenced by HaliInitBSP().

◆ MpsIRQTrapFrameToTrapFrame()

VOID MpsIRQTrapFrameToTrapFrame ( PKIRQ_TRAPFRAME  IrqTrapFrame,
PKTRAP_FRAME  TrapFrame 
)

Definition at line 708 of file apic.c.

710{
711#ifdef _M_AMD64
713#else
714 TrapFrame->SegGs = (USHORT)IrqTrapFrame->Gs;
715 TrapFrame->SegFs = (USHORT)IrqTrapFrame->Fs;
716 TrapFrame->SegEs = (USHORT)IrqTrapFrame->Es;
717 TrapFrame->SegDs = (USHORT)IrqTrapFrame->Ds;
718 TrapFrame->Eax = IrqTrapFrame->Eax;
719 TrapFrame->Ecx = IrqTrapFrame->Ecx;
720 TrapFrame->Edx = IrqTrapFrame->Edx;
721 TrapFrame->Ebx = IrqTrapFrame->Ebx;
722 TrapFrame->HardwareEsp = IrqTrapFrame->Esp;
723 TrapFrame->Ebp = IrqTrapFrame->Ebp;
724 TrapFrame->Esi = IrqTrapFrame->Esi;
725 TrapFrame->Edi = IrqTrapFrame->Edi;
726 TrapFrame->Eip = IrqTrapFrame->Eip;
727 TrapFrame->SegCs = IrqTrapFrame->Cs;
728 TrapFrame->EFlags = IrqTrapFrame->Eflags;
729#endif
730}
unsigned short USHORT
Definition: pedump.c:61
ULONG Eip
Definition: mps.h:26
ULONG Es
Definition: mps.h:16
ULONG Ds
Definition: mps.h:17
ULONG Fs
Definition: mps.h:15
ULONG Ecx
Definition: mps.h:19
ULONG Cs
Definition: mps.h:27
ULONG Ebp
Definition: mps.h:23
ULONG Eax
Definition: mps.h:18
ULONG Esi
Definition: mps.h:24
ULONG Eflags
Definition: mps.h:28
ULONG Esp
Definition: mps.h:22
ULONG Ebx
Definition: mps.h:21
ULONG Edi
Definition: mps.h:25
ULONG Gs
Definition: mps.h:14
ULONG Edx
Definition: mps.h:20
ULONG Edi
Definition: ketypes.h:316
ULONG EFlags
Definition: ketypes.h:458
ULONG Ebp
Definition: ketypes.h:319
ULONG Ebx
Definition: ketypes.h:318
ULONG HardwareEsp
Definition: ketypes.h:324
ULONG Ecx
Definition: ketypes.h:311
ULONG Eip
Definition: ketypes.h:321
USHORT SegCs
Definition: ketypes.h:454
USHORT SegEs
Definition: ketypes.h:439
USHORT SegFs
Definition: ketypes.h:440
USHORT SegGs
Definition: ketypes.h:441
ULONG Eax
Definition: ketypes.h:312
USHORT SegDs
Definition: ketypes.h:438
ULONG Esi
Definition: ketypes.h:317
ULONG Edx
Definition: ketypes.h:310

Referenced by MpsTimerHandler().

◆ MpsSpuriousHandler()

VOID MpsSpuriousHandler ( VOID  )

Definition at line 664 of file apic.c.

665{
666 ULONG tmp;
667
668 DPRINT("Spurious interrupt on CPU(%d)\n", ThisCPU());
669
670 tmp = APICRead(APIC_ISR + ((SPURIOUS_VECTOR & ~0x1f) >> 1));
671 if (tmp & (1 << (SPURIOUS_VECTOR & 0x1f)))
672 {
673 APICSendEOI();
674 return;
675 }
676#if 0
677 /* No need to send EOI here */
678 APICDump();
679#endif
680}

◆ MpsSpuriousInterrupt()

VOID MpsSpuriousInterrupt ( VOID  )

Referenced by HaliInitBSP().

◆ MpsTimerHandler()

VOID MpsTimerHandler ( ULONG  Vector,
PKIRQ_TRAPFRAME  Trapframe 
)

Definition at line 733 of file apic.c.

734{
735 KIRQL oldIrql;
736 KTRAP_FRAME KernelTrapFrame;
737#if 0
738 ULONG CPU;
739 static ULONG Count[MAX_CPU] = {0,};
740#endif
741 HalBeginSystemInterrupt(LOCAL_TIMER_VECTOR,
743 &oldIrql);
744 _enable();
745
746#if 0
747 CPU = ThisCPU();
748 if ((Count[CPU] % 100) == 0)
749 {
750 DbgPrint("(%s:%d) MpsTimerHandler on CPU%d, irql = %d, epi = %x, KPCR = %x\n", __FILE__, __LINE__, CPU, oldIrql,Trapframe->Eip, KeGetPcr());
751 }
752 Count[CPU]++;
753#endif
754
755 /* FIXME: SMP is totally broken */
756 MpsIRQTrapFrameToTrapFrame(Trapframe, &KernelTrapFrame);
758 {
759 //KeUpdateSystemTime(&KernelTrapFrame, oldIrql);
760 }
761 else
762 {
763 //KeUpdateRunTime(&KernelTrapFrame, oldIrql);
764 }
765
766 _disable();
767 HalEndSystemInterrupt (oldIrql, 0);
768}
BOOLEAN NTAPI HalBeginSystemInterrupt(IN KIRQL Irql, IN ULONG Vector, OUT PKIRQL OldIrql)
Definition: apic.c:749
UCHAR KIRQL
Definition: env_spec_w32.h:591
#define PROFILE_LEVEL
Definition: env_spec_w32.h:698
VOID NTAPI HalEndSystemInterrupt(IN KIRQL OldIrql, IN PKTRAP_FRAME TrapFrame)
Definition: pic.c:335
void __cdecl _disable(void)
Definition: intrin_arm.h:365
void __cdecl _enable(void)
Definition: intrin_arm.h:373
VOID MpsIRQTrapFrameToTrapFrame(PKIRQ_TRAPFRAME IrqTrapFrame, PKTRAP_FRAME TrapFrame)
Definition: apic.c:708
#define KeGetPcr()
Definition: ketypes.h:81
int Count
Definition: noreturn.cpp:7

◆ MpsTimerInterrupt()

VOID MpsTimerInterrupt ( VOID  )

Referenced by HaliInitBSP().

◆ Read8254Timer()

ULONG Read8254Timer ( VOID  )

◆ SetInterruptGate()

VOID SetInterruptGate ( ULONG  index,
ULONG_PTR  address 
)

Definition at line 849 of file apic.c.

850{
851#ifdef _M_AMD64
852 KIDTENTRY64 *idt;
853
854 idt = &KeGetPcr()->IdtBase[index];
855
856 idt->OffsetLow = address & 0xffff;
857 idt->Selector = KGDT_64_R0_CODE;
858 idt->IstIndex = 0;
859 idt->Reserved0 = 0;
860 idt->Type = 0x0e;
861 idt->Dpl = 0;
862 idt->Present = 1;
863 idt->OffsetMiddle = (address >> 16) & 0xffff;
864 idt->OffsetHigh = address >> 32;
865 idt->Reserved1 = 0;
866 idt->Alignment = 0;
867#else
868 KIDTENTRY *idt;
869 KIDT_ACCESS Access;
870
871 /* Set the IDT Access Bits */
872 Access.Reserved = 0;
873 Access.Present = 1;
874 Access.Dpl = 0; /* Kernel-Mode */
875 Access.SystemSegmentFlag = 0;
877
878 idt = (KIDTENTRY*)((ULONG)KeGetPcr()->IDT + index * sizeof(KIDTENTRY));
879 idt->Offset = (USHORT)(address & 0xffff);
880 idt->Selector = KGDT_R0_CODE;
881 idt->Access = Access.Value;
882 idt->ExtendedOffset = (USHORT)(address >> 16);
883#endif
884}
#define index(s, c)
Definition: various.h:29
GLuint index
Definition: glext.h:6031
#define KIDTENTRY
Definition: ketypes.h:553
#define I386_INTERRUPT_GATE
Definition: ketypes.h:113
UCHAR SystemSegmentFlag
Definition: ketypes.h:525
UCHAR Dpl
Definition: ketypes.h:526
UCHAR Reserved
Definition: ketypes.h:523
USHORT Value
Definition: ketypes.h:529
UCHAR SegmentType
Definition: ketypes.h:524
UCHAR Present
Definition: ketypes.h:527
ULONG OffsetHigh
Definition: ketypes.h:548
USHORT Reserved0
Definition: ketypes.h:543
USHORT IstIndex
Definition: ketypes.h:542
USHORT OffsetMiddle
Definition: ketypes.h:547
USHORT OffsetLow
Definition: ketypes.h:540
UINT64 Alignment
Definition: ketypes.h:551
ULONG Reserved1
Definition: ketypes.h:549
USHORT Dpl
Definition: ketypes.h:545
USHORT Present
Definition: ketypes.h:546
USHORT Selector
Definition: ketypes.h:541
USHORT Type
Definition: ketypes.h:544

Referenced by HaliInitBSP().

◆ VerifyLocalAPIC()

BOOLEAN VerifyLocalAPIC ( VOID  )

Definition at line 350 of file apic.c.

351{
352 SIZE_T reg0, reg1;
353 LARGE_INTEGER MsrValue;
354
355 /* The version register is read-only in a real APIC */
356 reg0 = APICRead(APIC_VER);
357 DPRINT1("Getting VERSION: %x\n", reg0);
358 APICWrite(APIC_VER, reg0 ^ APIC_VER_MASK);
359 reg1 = APICRead(APIC_VER);
360 DPRINT1("Getting VERSION: %x\n", reg1);
361
362 /*
363 * The two version reads above should print the same
364 * numbers. If the second one is different, then we
365 * poke at a non-APIC.
366 */
367
368 if (reg1 != reg0)
369 {
370 return FALSE;
371 }
372
373 /*
374 * Check if the version looks reasonably.
375 */
376 reg1 = GET_APIC_VERSION(reg0);
377 if (reg1 == 0x00 || reg1 == 0xff)
378 {
379 return FALSE;
380 }
381 reg1 = APICGetMaxLVT();
382 if (reg1 < 0x02 || reg1 == 0xff)
383 {
384 return FALSE;
385 }
386
387 /*
388 * The ID register is read/write in a real APIC.
389 */
390 reg0 = APICRead(APIC_ID);
391 DPRINT1("Getting ID: %x\n", reg0);
392 APICWrite(APIC_ID, reg0 ^ APIC_ID_MASK);
393 reg1 = APICRead(APIC_ID);
394 DPRINT1("Getting ID: %x\n", reg1);
395 APICWrite(APIC_ID, reg0);
396 if (reg1 != (reg0 ^ APIC_ID_MASK))
397 {
398 return FALSE;
399 }
400
401 MsrValue.QuadPart = __readmsr(0x1B /*MSR_IA32_APICBASE*/);
402
403 if (!(MsrValue.LowPart & /*MSR_IA32_APICBASE_ENABLE*/(1<<11)))
404 {
405 DPRINT1("Local APIC disabled by BIOS -- reenabling.\n");
406 MsrValue.LowPart &= ~/*MSR_IA32_APICBASE_BASE*/(1<<11);
407 MsrValue.LowPart |= /*MSR_IA32_APICBASE_ENABLE | APIC_DEFAULT_PHYS_BASE*/(1<<11)|0xfee00000;
408 __writemsr(0x1B /*MSR_IA32_APICBASE*/, MsrValue.HighPart);
409 }
410
411
412
413 return TRUE;
414}
PPC_QUAL void __writemsr(const unsigned long Value)
Definition: intrin_ppc.h:748
PPC_QUAL unsigned long long __readmsr()
Definition: intrin_ppc.h:741
ULONG_PTR SIZE_T
Definition: typedefs.h:80
LONGLONG QuadPart
Definition: typedefs.h:114
ULONG LowPart
Definition: typedefs.h:106

Referenced by HaliInitBSP().

◆ WaitFor8254Wraparound()

VOID WaitFor8254Wraparound ( VOID  )

Variable Documentation

◆ APend

CHAR * APend

Definition at line 70 of file apic.c.

Referenced by HaliInitBSP().

◆ APICBase

PULONG APICBase = (PULONG)APIC_DEFAULT_BASE

Definition at line 47 of file apic.c.

Referenced by HaliInitBSP().

◆ APICMode

ULONG APICMode

Definition at line 49 of file apic.c.

Referenced by APICSetup(), HaliGetSmpConfig(), and HaliInitBSP().

◆ APstart

CHAR* APstart
extern

Referenced by HaliInitBSP().

◆ BootCPU

ULONG BootCPU

Definition at line 38 of file apic.c.

Referenced by APICSetup(), HaliInitBSP(), and HaliMPProcessorInfo().

◆ CPUCount

ULONG CPUCount

Definition at line 37 of file apic.c.

Referenced by HalAllProcessorsStarted(), HaliMPProcessorInfo(), and HalStartNextProcessor().

◆ CPUMap

CPU_INFO CPUMap[MAX_CPU]

Definition at line 40 of file apic.c.

Referenced by APICCalibrateTimer(), APICSetup(), HaliMPProcessorInfo(), and HalInitializeProcessor().

◆ KernelBase

ULONG_PTR KernelBase
extern

Definition at line 20 of file halinit_mp.c.

Referenced by HalpInitPhase0(), and LoadWindowsCore().

◆ lastregr

ULONG lastregr[MAX_CPU]

Definition at line 52 of file apic.c.

Referenced by APICDump().

◆ lastregw

ULONG lastregw[MAX_CPU]

Definition at line 54 of file apic.c.

Referenced by APICDump().

◆ lastvalr

ULONG lastvalr[MAX_CPU]

Definition at line 53 of file apic.c.

Referenced by APICDump().

◆ lastvalw

ULONG lastvalw[MAX_CPU]

Definition at line 55 of file apic.c.

Referenced by APICDump().

◆ OnlineCPUs

ULONG OnlineCPUs

Definition at line 39 of file apic.c.

Referenced by HalAllProcessorsStarted(), HalInitializeProcessor(), and HalStartNextProcessor().