Split some of the halmp files according its functions. Modified: trunk/reactos/hal/halx86/generic/timer.c Modified: trunk/reactos/hal/halx86/include/apic.h Modified: trunk/reactos/hal/halx86/include/hal.h Added: trunk/reactos/hal/halx86/include/ioapic.h Modified: trunk/reactos/hal/halx86/include/mps.h Modified: trunk/reactos/hal/halx86/mp/Makefile Modified: trunk/reactos/hal/halx86/mp/apic.c Modified: trunk/reactos/hal/halx86/mp/halinit_mp.c Added: trunk/reactos/hal/halx86/mp/ioapic.c Added: trunk/reactos/hal/halx86/mp/mpconfig.c Modified: trunk/reactos/hal/halx86/mp/mpsirql.c Modified: trunk/reactos/hal/halx86/mp/processor_mp.c _____
Modified: trunk/reactos/hal/halx86/generic/timer.c --- trunk/reactos/hal/halx86/generic/timer.c 2005-03-07 16:37:49 UTC (rev 13867) +++ trunk/reactos/hal/halx86/generic/timer.c 2005-03-07 16:40:32 UTC (rev 13868) @@ -165,7 +165,7 @@
}
-static VOID WaitFor8254Wraparound(VOID) +VOID WaitFor8254Wraparound(VOID) { ULONG CurCount, PrevCount = ~0; LONG Delta; _____
Modified: trunk/reactos/hal/halx86/include/apic.h --- trunk/reactos/hal/halx86/include/apic.h 2005-03-07 16:37:49 UTC (rev 13867) +++ trunk/reactos/hal/halx86/include/apic.h 2005-03-07 16:40:32 UTC (rev 13868) @@ -145,7 +145,16 @@
#define APIC_INTEGRATED(version) (version & 0xF0)
+typedef enum { + amPIC = 0, /* IMCR and PIC compatibility mode */ + amVWIRE /* Virtual Wire compatibility mode */ +} APIC_MODE; + +#ifdef CONFIG_SMP #define MAX_CPU 32 +#else +#define MAX_CPU 1 +#endif
/* * Local APIC timer IRQ vector is on a different priority level, @@ -158,6 +167,11 @@ #define ERROR_VECTOR 0xFE #define SPURIOUS_VECTOR 0xFF /* Must be 0xXF */
+/* CPU flags */ +#define CPU_USABLE 0x01 /* 1 if the CPU is usable (ie. can be used) */ +#define CPU_ENABLED 0x02 /* 1 if the CPU is enabled */ +#define CPU_BSP 0x04 /* 1 if the CPU is the bootstrap processor */ +#define CPU_TSC 0x08 /* 1 if the CPU has a time stamp counter */
typedef struct _CPU_INFO { @@ -170,23 +184,26 @@ UCHAR Padding[16-12]; /* Padding to 16-byte */ } CPU_INFO, *PCPU_INFO;
+extern ULONG CPUCount; /* Total number of CPUs */ +extern ULONG BootCPU; /* Bootstrap processor */ +extern ULONG OnlineCPUs; /* Bitmask of online CPUs */ +extern CPU_INFO CPUMap[MAX_CPU]; /* Map of all CPUs in the system */
/* Prototypes */
- +inline VOID APICWrite(ULONG Offset, ULONG Value); inline ULONG APICRead(ULONG Offset); -inline VOID APICWrite(ULONG Offset, ULONG Value); VOID APICSendIPI(ULONG Target, ULONG Mode); - -ULONG APICGetMaxLVT(VOID); VOID APICSetup(VOID); VOID HaliInitBSP(VOID); VOID APICSyncArbIDs(VOID); inline VOID APICSendEOI(VOID); +VOID APICCalibrateTimer(ULONG CPU); +VOID HaliStartApplicationProcessor(ULONG Cpu, ULONG Stack);
static inline ULONG ThisCPU(VOID) { - return (APICRead(APIC_ID) & APIC_ID_MASK) >> 24; + return (APICRead(APIC_ID) & APIC_ID_MASK) >> 24; }
_____
Modified: trunk/reactos/hal/halx86/include/hal.h --- trunk/reactos/hal/halx86/include/hal.h 2005-03-07 16:37:49 UTC (rev 13867) +++ trunk/reactos/hal/halx86/include/hal.h 2005-03-07 16:40:32 UTC (rev 13868) @@ -413,6 +413,8 @@
#define Ki386EnableInterrupts() __asm__ __volatile__("sti\n\t") #define Ki386HaltProcessor() __asm__ __volatile__("hlt\n\t") #define Ki386RdTSC(x) __asm__ __volatile__("rdtsc\n\t" : "=A" (x.u.LowPart), "=d" (x.u.HighPart)); +#define Ki386Rdmsr(msr,val1,val2) __asm__ __volatile__("rdmsr" : "=a" (val1), "=d" (val2) : "c" (msr)) +#define Ki386Wrmsr(msr,val1,val2) __asm__ __volatile__("wrmsr" : /* no outputs */ : "c" (msr), "a" (val1), "d" (val2))
static inline BYTE Ki386ReadFsByte(ULONG offset) { _____
Added: trunk/reactos/hal/halx86/include/ioapic.h --- trunk/reactos/hal/halx86/include/ioapic.h 2005-03-07 16:37:49 UTC (rev 13867) +++ trunk/reactos/hal/halx86/include/ioapic.h 2005-03-07 16:40:32 UTC (rev 13868) @@ -0,0 +1,101 @@
+/* + * + */ + +#ifndef __INTERNAL_HAL_IOAPIC_H +#define __INTERNAL_HAL_IOAPIC_H + +/* I/O APIC Register Address Map */ +#define IOAPIC_IOREGSEL 0x0000 /* I/O Register Select (index) (R/W) */ +#define IOAPIC_IOWIN 0x0010 /* I/O window (data) (R/W) */ + +#define IOAPIC_ID 0x0000 /* IO APIC ID (R/W) */ +#define IOAPIC_VER 0x0001 /* IO APIC Version (R) */ +#define IOAPIC_ARB 0x0002 /* IO APIC Arbitration ID (R) */ +#define IOAPIC_REDTBL 0x0010 /* Redirection Table (0-23 64-bit registers) (R/W) */ + +#define IOAPIC_ID_MASK (0xF << 24) +#define GET_IOAPIC_ID(x) (((x) & IOAPIC_ID_MASK) >> 24) +#define SET_IOAPIC_ID(x) ((x) << 24) + +#define IOAPIC_VER_MASK (0xFF) +#define GET_IOAPIC_VERSION(x) (((x) & IOAPIC_VER_MASK)) +#define IOAPIC_MRE_MASK (0xFF << 16) /* Maximum Redirection Entry */ +#define GET_IOAPIC_MRE(x) (((x) & IOAPIC_MRE_MASK) >> 16) + +#define IOAPIC_ARB_MASK (0xF << 24) +#define GET_IOAPIC_ARB(x) (((x) & IOAPIC_ARB_MASK) >> 24) + +#define IOAPIC_TBL_DELMOD (0x7 << 10) /* Delivery Mode (see APIC_DM_*) */ +#define IOAPIC_TBL_DM (0x1 << 11) /* Destination Mode */ +#define IOAPIC_TBL_DS (0x1 << 12) /* Delivery Status */ +#define IOAPIC_TBL_INTPOL (0x1 << 13) /* Interrupt Input Pin Polarity */ +#define IOAPIC_TBL_RIRR (0x1 << 14) /* Remote IRR */ +#define IOAPIC_TBL_TM (0x1 << 15) /* Trigger Mode */ +#define IOAPIC_TBL_IM (0x1 << 16) /* Interrupt Mask */ +#define IOAPIC_TBL_DF0 (0xF << 56) /* Destination Field (physical mode) */ +#define IOAPIC_TBL_DF1 (0xFF<< 56) /* Destination Field (logical mode) */ +#define IOAPIC_TBL_VECTOR (0xFF << 0) /* Vector (10h - FEh) */ + +typedef struct _IOAPIC_ROUTE_ENTRY { + ULONG vector : 8, + delivery_mode : 3, /* 000: FIXED + * 001: lowest priority + * 111: ExtINT + */ + dest_mode : 1, /* 0: physical, 1: logical */ + delivery_status : 1, + polarity : 1, + irr : 1, + trigger : 1, /* 0: edge, 1: level */ + mask : 1, /* 0: enabled, 1: disabled */ + __reserved_2 : 15; + + union { + struct { + ULONG __reserved_1 : 24, + physical_dest : 4, + __reserved_2 : 4; + } physical; + struct { + ULONG __reserved_1 : 24, + logical_dest : 8; + } logical; + } dest; +} __attribute__ ((packed)) IOAPIC_ROUTE_ENTRY, *PIOAPIC_ROUTE_ENTRY; + +typedef struct _IOAPIC_INFO +{ + ULONG ApicId; /* APIC ID */ + ULONG ApicVersion; /* APIC version */ + ULONG ApicAddress; /* APIC address */ + ULONG EntryCount; /* Number of redirection entries */ +} IOAPIC_INFO, *PIOAPIC_INFO; + +#define IOAPIC_DEFAULT_BASE 0xFEC00000 /* Default I/O APIC Base Register Address */ + +extern ULONG IRQCount; /* Number of IRQs */ +extern UCHAR BUSMap[MAX_BUS]; /* Map of all buses in the system */ +extern UCHAR PCIBUSMap[MAX_BUS]; /* Map of all PCI buses in the system */ +extern IOAPIC_INFO IOAPICMap[MAX_IOAPIC]; /* Map of all I/O APICs in the system */ +extern ULONG IOAPICCount; /* Number of I/O APICs in the system */ +extern ULONG APICMode; /* APIC mode at startup */ +extern MP_CONFIGURATION_INTSRC IRQMap[MAX_IRQ_SOURCE]; /* Map of all IRQs */ + +VOID IOAPICSetupIrqs(VOID); +VOID IOAPICEnable(VOID); +VOID IOAPICSetupIds(VOID); +VOID IOAPICMaskIrq(ULONG Irq); +VOID IOAPICUnmaskIrq(ULONG Irq); + +VOID HaliReconfigurePciInterrupts(VOID); + +/* For debugging */ +VOID IOAPICDump(VOID); + +#endif + + + +/* EOF */ + _____
Modified: trunk/reactos/hal/halx86/include/mps.h --- trunk/reactos/hal/halx86/include/mps.h 2005-03-07 16:37:49 UTC (rev 13867) +++ trunk/reactos/hal/halx86/include/mps.h 2005-03-07 16:40:32 UTC (rev 13868) @@ -9,77 +9,7 @@
#define IRQL2TPR(irql) ((irql) >= IPI_LEVEL ? IPI_VECTOR : ((irql)
= PROFILE_LEVEL ? LOCAL_TIMER_VECTOR : ((irql) > DISPATCH_LEVEL ?
IRQL2VECTOR(irql) : 0)))
-#define IOAPIC_DEFAULT_BASE 0xFEC00000 /* Default I/O APIC Base Register Address */
-/* I/O APIC Register Address Map */ -#define IOAPIC_IOREGSEL 0x0000 /* I/O Register Select (index) (R/W) */ -#define IOAPIC_IOWIN 0x0010 /* I/O window (data) (R/W) */ - -#define IOAPIC_ID 0x0000 /* IO APIC ID (R/W) */ -#define IOAPIC_VER 0x0001 /* IO APIC Version (R) */ -#define IOAPIC_ARB 0x0002 /* IO APIC Arbitration ID (R) */ -#define IOAPIC_REDTBL 0x0010 /* Redirection Table (0-23 64-bit registers) (R/W) */ - -#define IOAPIC_ID_MASK (0xF << 24) -#define GET_IOAPIC_ID(x) (((x) & IOAPIC_ID_MASK) >> 24) -#define SET_IOAPIC_ID(x) ((x) << 24) - -#define IOAPIC_VER_MASK (0xFF) -#define GET_IOAPIC_VERSION(x) (((x) & IOAPIC_VER_MASK)) -#define IOAPIC_MRE_MASK (0xFF << 16) /* Maximum Redirection Entry */ -#define GET_IOAPIC_MRE(x) (((x) & IOAPIC_MRE_MASK) >> 16) - -#define IOAPIC_ARB_MASK (0xF << 24) -#define GET_IOAPIC_ARB(x) (((x) & IOAPIC_ARB_MASK) >> 24) - -#define IOAPIC_TBL_DELMOD (0x7 << 10) /* Delivery Mode (see APIC_DM_*) */ -#define IOAPIC_TBL_DM (0x1 << 11) /* Destination Mode */ -#define IOAPIC_TBL_DS (0x1 << 12) /* Delivery Status */ -#define IOAPIC_TBL_INTPOL (0x1 << 13) /* Interrupt Input Pin Polarity */ -#define IOAPIC_TBL_RIRR (0x1 << 14) /* Remote IRR */ -#define IOAPIC_TBL_TM (0x1 << 15) /* Trigger Mode */ -#define IOAPIC_TBL_IM (0x1 << 16) /* Interrupt Mask */ -#define IOAPIC_TBL_DF0 (0xF << 56) /* Destination Field (physical mode) */ -#define IOAPIC_TBL_DF1 (0xFF<< 56) /* Destination Field (logical mode) */ -#define IOAPIC_TBL_VECTOR (0xFF << 0) /* Vector (10h - FEh) */ - -typedef struct _IOAPIC_ROUTE_ENTRY { - ULONG vector : 8, - delivery_mode : 3, /* 000: FIXED - * 001: lowest priority - * 111: ExtINT - */ - dest_mode : 1, /* 0: physical, 1: logical */ - delivery_status : 1, - polarity : 1, - irr : 1, - trigger : 1, /* 0: edge, 1: level */ - mask : 1, /* 0: enabled, 1: disabled */ - __reserved_2 : 15; - - union { struct { ULONG - __reserved_1 : 24, - physical_dest : 4, - __reserved_2 : 4; - } physical; - - struct { ULONG - __reserved_1 : 24, - logical_dest : 8; - } logical; - } dest; -} __attribute__ ((packed)) IOAPIC_ROUTE_ENTRY, *PIOAPIC_ROUTE_ENTRY; - -typedef struct _IOAPIC_INFO -{ - ULONG ApicId; /* APIC ID */ - ULONG ApicVersion; /* APIC version */ - ULONG ApicAddress; /* APIC address */ - ULONG EntryCount; /* Number of redirection entries */ -} IOAPIC_INFO, *PIOAPIC_INFO; - - - #if 0 /* This values are defined in halirql.h */ #define FIRST_DEVICE_VECTOR 0x30 @@ -148,14 +78,8 @@ } __attribute__((packed)) MP_CONFIGURATION_PROCESSOR, *PMP_CONFIGURATION_PROCESSOR;
-#define CPU_FLAG_ENABLED 1 /* Processor is available */ -#define CPU_FLAG_BSP 2 /* Processor is the bootstrap processor */
-#define CPU_STEPPING_MASK 0x0F -#define CPU_MODEL_MASK 0xF0 -#define CPU_FAMILY_MASK 0xF00
- typedef struct __attribute__((packed)) _MP_CONFIGURATION_BUS { UCHAR Type; /* 1 */ @@ -239,54 +163,20 @@ } MP_CONFIGURATION_INTLOCAL, *PMP_CONFIGURATION_INTLOCAL;
#define MP_APIC_ALL 0xFF - - -static inline VOID ReadPentiumClock(PULARGE_INTEGER Count) -{ - register ULONG nLow; - register ULONG nHigh;
-#if defined(__GNUC__) - __asm__ __volatile__ ("rdtsc" : "=a" (nLow), "=d" (nHigh)); -#elif defined(_MSC_VER) - __asm rdtsc - __asm mov nLow, eax - __asm mov nHigh, edx -#else -#error Unknown compiler for inline assembler -#endif +#define CPU_FLAG_ENABLED 1 /* Processor is available */ +#define CPU_FLAG_BSP 2 /* Processor is the bootstrap processor */
- Count->u.LowPart = nLow; - Count->u.HighPart = nHigh; -} +#define CPU_STEPPING_MASK 0x0F +#define CPU_MODEL_MASK 0xF0 +#define CPU_FAMILY_MASK 0xF00
- - - -/* CPU flags */ -#define CPU_USABLE 0x01 /* 1 if the CPU is usable (ie. can be used) */ -#define CPU_ENABLED 0x02 /* 1 if the CPU is enabled */ -#define CPU_BSP 0x04 /* 1 if the CPU is the bootstrap processor */ - - -typedef enum { - amPIC = 0, /* IMCR and PIC compatibility mode */ - amVWIRE /* Virtual Wire compatibility mode */ -} APIC_MODE; - - #define PIC_IRQS 16
/* Prototypes */
VOID HalpInitMPS(VOID); -ULONG IOAPICRead(ULONG Apic, ULONG Offset); -VOID IOAPICWrite(ULONG Apic, ULONG Offset, ULONG Value); -VOID IOAPICMaskIrq(ULONG Irq); -VOID IOAPICUnmaskIrq(ULONG Irq);
-/* For debugging */ -VOID IOAPICDump(VOID);
#endif /* __INCLUDE_HAL_MPS */
_____
Modified: trunk/reactos/hal/halx86/mp/Makefile --- trunk/reactos/hal/halx86/mp/Makefile 2005-03-07 16:37:49 UTC (rev 13867) +++ trunk/reactos/hal/halx86/mp/Makefile 2005-03-07 16:40:32 UTC (rev 13868) @@ -61,7 +61,9 @@
MP_OBJECTS = \ apic.o \ halinit_mp.o \ + ioapic.o \ ipi_mp.o \ + mpconfig.o \ mpsirql.o \ mpsboot.o \ mps.o \ _____
Modified: trunk/reactos/hal/halx86/mp/apic.c --- trunk/reactos/hal/halx86/mp/apic.c 2005-03-07 16:37:49 UTC (rev 13867) +++ trunk/reactos/hal/halx86/mp/apic.c 2005-03-07 16:40:32 UTC (rev 13868) @@ -1,6 +1,6 @@
/* * ReactOS kernel - * Copyright (C) 2004 ReactOS Team + * Copyright (C) 2004, 2005 ReactOS Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -25,6 +25,8 @@ * PROGRAMMER: */
+/* INCLUDE ***********************************************************************/ + #include <ddk/ntddk.h> #include <internal/i386/ps.h>
@@ -36,23 +38,47 @@ #define NDEBUG #include <internal/debug.h>
-BOOLEAN VerifyLocalAPIC(VOID); -VOID APICCalibrateTimer(ULONG CPU); +/* GLOBALS ***********************************************************************/
-extern VOID MpsTimerInterrupt(VOID); -extern VOID MpsErrorInterrupt(VOID); -extern VOID MpsSpuriousInterrupt(VOID); -extern VOID MpsIpiInterrupt(VOID); +ULONG CPUCount; /* Total number of CPUs */ +ULONG BootCPU; /* Bootstrap processor */ +ULONG OnlineCPUs; /* Bitmask of online CPUs */ +CPU_INFO CPUMap[MAX_CPU]; /* Map of all CPUs in the system */
-extern ULONG APICMode; /* APIC mode at startup */ -extern PULONG BIOSBase; /* Virtual address of BIOS data segment */ -extern PULONG CommonBase; /* Virtual address of common area */ -extern ULONG BootCPU; /* Bootstrap processor */ -extern ULONG OnlineCPUs; /* Bitmask of online CPUs */ +#ifdef CONFIG_SMP +PULONG BIOSBase; /* Virtual address of BIOS data segment */ +PULONG CommonBase; /* Virtual address of common area */ +#endif
-extern CHAR *APstart, *APend; -extern VOID (*APflush)(VOID); +PULONG APICBase = (PULONG)APIC_DEFAULT_BASE; /* Virtual address of local APIC */
+ULONG APICMode; /* APIC mode at startup */ + +/* For debugging */ +ULONG lastregr[MAX_CPU]; +ULONG lastvalr[MAX_CPU]; +ULONG lastregw[MAX_CPU]; +ULONG lastvalw[MAX_CPU]; + +#ifdef CONFIG_SMP +typedef struct __attribute__((packed)) _COMMON_AREA_INFO +{ + ULONG Stack; /* Location of AP stack */ + ULONG PageDirectory; /* Page directory for an AP */ + ULONG NtProcessStartup; /* Kernel entry point for an AP */ + ULONG PaeModeEnabled; /* PAE mode is enabled */ + ULONG Debug[16]; /* For debugging */ +} COMMON_AREA_INFO, *PCOMMON_AREA_INFO; +#endif + +CHAR *APstart, *APend; + +#define BIOS_AREA 0x0 +#define COMMON_AREA 0x2000 + +#define HZ (100) +#define APIC_DIVISOR (16) + #define CMOS_READ(address) ({ \ WRITE_PORT_UCHAR((PUCHAR)0x70, address)); \ READ_PORT_UCHAR((PUCHAR)0x71)); \ @@ -63,20 +89,17 @@ WRITE_PORT_UCHAR((PUCHAR)0x71, value); \ })
-#define BIOS_AREA 0x0 -#define COMMON_AREA 0x2000 +extern PVOID IMPORTED MmSystemRangeStart;
+/* FUNCTIONS *********************************************************************/
-extern CPU_INFO CPUMap[MAX_CPU]; /* Map of all CPUs in the system */ +extern ULONG Read8254Timer(VOID); +extern VOID WaitFor8254Wraparound(VOID); +extern VOID MpsTimerInterrupt(VOID); +extern VOID MpsErrorInterrupt(VOID); +extern VOID MpsSpuriousInterrupt(VOID); +extern VOID MpsIpiInterrupt(VOID);
-PULONG APICBase = (PULONG)APIC_DEFAULT_BASE; /* Virtual address of local APIC */ - -/* For debugging */ -ULONG lastregr[MAX_CPU]; -ULONG lastvalr[MAX_CPU]; -ULONG lastregw[MAX_CPU]; -ULONG lastvalw[MAX_CPU]; - ULONG APICGetMaxLVT(VOID) { ULONG tmp, ver, maxlvt; @@ -152,7 +175,7 @@ }
/* Enable symetric I/O mode ie. connect the BSP's local APIC to INT and NMI lines */ -VOID EnableSMPMode(VOID) +VOID EnableApicMode(VOID) { /* * Do not trust the local APIC being empty at bootup. @@ -203,64 +226,7 @@ APICWrite(APIC_SIVR, tmp); }
-VOID HaliInitBSP(VOID) -{ - PUSHORT ps; - static BOOLEAN BSPInitialized = FALSE;
- /* Only initialize the BSP once */ - if (BSPInitialized) - { - KEBUGCHECK(0); - return; - } - - BSPInitialized = TRUE; - - DPRINT("APIC is mapped at 0x%X\n", APICBase); - - if (VerifyLocalAPIC()) - { - DPRINT("APIC found\n"); - } - else - { - DPRINT("No APIC found\n"); - KEBUGCHECK(0); - } - - if (APICMode == amPIC) - { - EnableSMPMode(); - } - - APICSetup(); - - /* BIOS data segment */ - BIOSBase = (PULONG)BIOS_AREA; - - /* Area for communicating with the APs */ - CommonBase = (PULONG)COMMON_AREA; - - /* Copy bootstrap code to common area */ - memcpy((PVOID)((ULONG)CommonBase + PAGE_SIZE), - &APstart, - (ULONG)&APend - (ULONG)&APstart + 1); - - /* Set shutdown code */ - CMOS_WRITE(0xF, 0xA); - - /* Set warm reset vector */ - ps = (PUSHORT)((ULONG)BIOSBase + 0x467); - *ps = (COMMON_AREA + PAGE_SIZE) & 0xF; - - ps = (PUSHORT)((ULONG)BIOSBase + 0x469); - *ps = (COMMON_AREA + PAGE_SIZE) >> 4; - - /* Calibrate APIC timer */ - APICCalibrateTimer(BootCPU); -} - inline ULONG _APICRead(ULONG Offset) { PULONG p; @@ -455,7 +421,6 @@ BOOLEAN VerifyLocalAPIC(VOID) { UINT reg0, reg1; - CHECKPOINT1; /* The version register is read-only in a real APIC */ reg0 = APICRead(APIC_VER); DPRINT1("Getting VERSION: %x\n", reg0); @@ -502,9 +467,23 @@ return FALSE; }
+ ULONG l, h; + Ki386Rdmsr(0x1b /*MSR_IA32_APICBASE*/, l, h); + + if (!(l & /*MSR_IA32_APICBASE_ENABLE*/(1<<11))) + { + DPRINT1("Local APIC disabled by BIOS -- reenabling.\n"); + l &= ~/*MSR_IA32_APICBASE_BASE*/(1<<11); + l |= /*MSR_IA32_APICBASE_ENABLE | APIC_DEFAULT_PHYS_BASE*/(1<<11)|0xfee00000; + Ki386Wrmsr(0x1b/*MSR_IA32_APICBASE*/, l, h); + } + + + return TRUE; }
+#ifdef CONFIG_SMP VOID APICSendIPI(ULONG Target, ULONG Mode) { ULONG tmp, i, flags; @@ -568,6 +547,7 @@ } Ki386RestoreFlags(flags); } +#endif
VOID APICSetup(VOID) { @@ -651,7 +631,6 @@ } APICWrite(APIC_LINT0, tmp);
- /* * Only the BSP should see the LINT1 NMI signal, obviously. */ @@ -697,7 +676,7 @@ DPRINT("ESR value after enabling vector: 0x%X\n", tmp); } } - +#ifdef CONFIG_SMP VOID APICSyncArbIDs(VOID) { ULONG i, tmp; @@ -720,6 +699,7 @@ DPRINT("Synchronizing Arb IDs.\n"); APICWrite(APIC_ICR0, APIC_ICR0_DESTS_ALL | APIC_ICR0_LEVEL | APIC_DM_INIT); } +#endif
VOID MpsErrorHandler(VOID) { @@ -769,12 +749,13 @@ #endif }
+#ifdef CONFIG_SMP VOID MpsIpiHandler(VOID) { KIRQL oldIrql;
HalBeginSystemInterrupt(IPI_VECTOR, - VECTOR2IRQL(IPI_VECTOR), + IPI_LEVEL, &oldIrql); Ki386EnableInterrupts(); #if 0 @@ -791,6 +772,7 @@ Ki386DisableInterrupts(); HalEndSystemInterrupt(oldIrql, 0); } +#endif
VOID MpsIRQTrapFrameToTrapFrame(PKIRQ_TRAPFRAME IrqTrapFrame, @@ -823,7 +805,7 @@ static ULONG Count[MAX_CPU] = {0,}; #endif HalBeginSystemInterrupt(LOCAL_TIMER_VECTOR, - VECTOR2IRQL(LOCAL_TIMER_VECTOR), + PROFILE_LEVEL, &oldIrql); Ki386EnableInterrupts();
@@ -850,4 +832,318 @@ HalEndSystemInterrupt (oldIrql, 0); }
+VOID APICSetupLVTT(ULONG ClockTicks) +{ + ULONG tmp; + + tmp = GET_APIC_VERSION(APICRead(APIC_VER)); + if (!APIC_INTEGRATED(tmp)) + { + tmp = SET_APIC_TIMER_BASE(APIC_TIMER_BASE_DIV) | APIC_LVT_PERIODIC | LOCAL_TIMER_VECTOR;; + } + else + { + /* Periodic timer */ + tmp = APIC_LVT_PERIODIC | LOCAL_TIMER_VECTOR;; + } + APICWrite(APIC_LVTT, tmp); + + tmp = APICRead(APIC_TDCR); + tmp &= ~(APIC_TDCR_1 | APIC_TIMER_BASE_DIV); + tmp |= APIC_TDCR_16; + APICWrite(APIC_TDCR, tmp); + APICWrite(APIC_ICRT, ClockTicks / APIC_DIVISOR); +} + +VOID +APICCalibrateTimer(ULONG CPU) +{ + ULARGE_INTEGER t1, t2; + LONG tt1, tt2; + BOOLEAN TSCPresent; + + DPRINT("Calibrating APIC timer for CPU %d\n", CPU); + + APICSetupLVTT(1000000000); + + TSCPresent = KeGetCurrentKPCR()->PrcbData.FeatureBits & X86_FEATURE_TSC ? TRUE : FALSE; + + /* + * The timer chip counts down to zero. Let's wait + * for a wraparound to start exact measurement: + * (the current tick might have been already half done) + */ + WaitFor8254Wraparound(); + + /* + * We wrapped around just now. Let's start + */ + if (TSCPresent) + { + Ki386RdTSC(t1); + } + tt1 = APICRead(APIC_CCRT); + + WaitFor8254Wraparound(); + + + tt2 = APICRead(APIC_CCRT); + if (TSCPresent) + { + Ki386RdTSC(t2); + CPUMap[CPU].CoreSpeed = (HZ * (t2.QuadPart - t1.QuadPart)); + DPRINT("CPU clock speed is %ld.%04ld MHz.\n", + CPUMap[CPU].CoreSpeed/1000000, + CPUMap[CPU].CoreSpeed%1000000); + KeGetCurrentKPCR()->PrcbData.MHz = CPUMap[CPU].CoreSpeed/1000000; + } + + CPUMap[CPU].BusSpeed = (HZ * (long)(tt1 - tt2) * APIC_DIVISOR); + + /* Setup timer for normal operation */ +// APICSetupLVTT((CPUMap[CPU].BusSpeed / 1000000) * 100); // 100ns + APICSetupLVTT((CPUMap[CPU].BusSpeed / 1000000) * 10000); // 10ms +// APICSetupLVTT((CPUMap[CPU].BusSpeed / 1000000) * 100000); // 100ms + + DPRINT("Host bus clock speed is %ld.%04ld MHz.\n", + CPUMap[CPU].BusSpeed/1000000, + CPUMap[CPU].BusSpeed%1000000); +} + +VOID +SetInterruptGate(ULONG index, ULONG address) +{ + IDT_DESCRIPTOR *idt; + + idt = (IDT_DESCRIPTOR*)((ULONG)KeGetCurrentKPCR()->IDT + index * sizeof(IDT_DESCRIPTOR)); + idt->a = (((ULONG)address)&0xffff) + (KERNEL_CS << 16); + idt->b = 0x8e00 + (((ULONG)address)&0xffff0000); +} + +VOID HaliInitBSP(VOID) +{ +#ifdef CONFIG_SMP + PUSHORT ps; +#endif + + static BOOLEAN BSPInitialized = FALSE; + + /* Only initialize the BSP once */ + if (BSPInitialized) + { + KEBUGCHECK(0); + return; + } + + BSPInitialized = TRUE; + + /* Setup interrupt handlers */ + SetInterruptGate(LOCAL_TIMER_VECTOR, (ULONG)MpsTimerInterrupt); + SetInterruptGate(ERROR_VECTOR, (ULONG)MpsErrorInterrupt); + SetInterruptGate(SPURIOUS_VECTOR, (ULONG)MpsSpuriousInterrupt); +#ifdef CONFIG_SMP + SetInterruptGate(IPI_VECTOR, (ULONG)MpsIpiInterrupt); +#endif + DPRINT("APIC is mapped at 0x%X\n", APICBase); + + if (VerifyLocalAPIC()) + { + DPRINT("APIC found\n"); + } + else + { + DPRINT("No APIC found\n"); + KEBUGCHECK(0); + } + + if (APICMode == amPIC) + { + EnableApicMode(); + } + + APICSetup(); + +#ifdef CONFIG_SMP + /* BIOS data segment */ + BIOSBase = (PULONG)BIOS_AREA; + + /* Area for communicating with the APs */ + CommonBase = (PULONG)COMMON_AREA; + + /* Copy bootstrap code to common area */ + memcpy((PVOID)((ULONG)CommonBase + PAGE_SIZE), + &APstart, + (ULONG)&APend - (ULONG)&APstart + 1); + + /* Set shutdown code */ + CMOS_WRITE(0xF, 0xA); + + /* Set warm reset vector */ + ps = (PUSHORT)((ULONG)BIOSBase + 0x467); + *ps = (COMMON_AREA + PAGE_SIZE) & 0xF; + + ps = (PUSHORT)((ULONG)BIOSBase + 0x469); + *ps = (COMMON_AREA + PAGE_SIZE) >> 4; +#endif + + /* Calibrate APIC timer */ + APICCalibrateTimer(BootCPU); +} + +#ifdef CONFIG_SMP +VOID +HaliStartApplicationProcessor(ULONG Cpu, ULONG Stack) +{ + ULONG tmp, maxlvt; + PCOMMON_AREA_INFO Common; + ULONG StartupCount; + ULONG i, j; + ULONG DeliveryStatus = 0; + ULONG AcceptStatus = 0; + + if (Cpu >= MAX_CPU || + Cpu >= CPUCount || + OnlineCPUs & (1 << Cpu)) + { + KEBUGCHECK(0); + } + DPRINT1("Attempting to boot CPU %d\n", Cpu); + + /* Send INIT IPI */ + + APICSendIPI(Cpu, APIC_DM_INIT|APIC_ICR0_LEVEL_ASSERT); + + KeStallExecutionProcessor(200); + + /* Deassert INIT */ + + APICSendIPI(Cpu, APIC_DM_INIT|APIC_ICR0_LEVEL_DEASSERT); + + if (APIC_INTEGRATED(CPUMap[Cpu].APICVersion)) + { + /* Clear APIC errors */ + APICWrite(APIC_ESR, 0); + tmp = (APICRead(APIC_ESR) & APIC_ESR_MASK); + } + + Common = (PCOMMON_AREA_INFO)CommonBase; + + /* Write the location of the AP stack */ + Common->Stack = (ULONG)Stack; + /* Write the page directory page */ + Ke386GetPageTableDirectory(Common->PageDirectory); + /* Write the kernel entry point */ + Common->NtProcessStartup = (ULONG_PTR)RtlImageNtHeader(MmSystemRangeStart)->OptionalHeader.AddressO fEntryPoint + (ULONG_PTR)MmSystemRangeStart; + /* Write the state of the mae mode */ + Common->PaeModeEnabled = Ke386GetCr4() & X86_CR4_PAE ? 1 : 0; + + DPRINT1("%x %x %x %x\n", Common->Stack, Common->PageDirectory, Common->NtProcessStartup, Common->PaeModeEnabled); + + DPRINT("Cpu %d got stack at 0x%X\n", Cpu, Common->Stack); +#if 0 + for (j = 0; j < 16; j++) + { + Common->Debug[j] = 0; + } +#endif + + maxlvt = APICGetMaxLVT(); + + /* Is this a local APIC or an 82489DX? */ + StartupCount = (APIC_INTEGRATED(CPUMap[Cpu].APICVersion)) ? 2 : 0; + + for (i = 1; i <= StartupCount; i++) + { + /* It's a local APIC, so send STARTUP IPI */ + DPRINT("Sending startup signal %d\n", i); + /* Clear errors */ + APICWrite(APIC_ESR, 0); + APICRead(APIC_ESR); + + APICSendIPI(Cpu, APIC_DM_STARTUP | ((COMMON_AREA + PAGE_SIZE) >> 12)|APIC_ICR0_LEVEL_DEASSERT); + + /* Wait up to 10ms for IPI to be delivered */ + j = 0; + do + { + KeStallExecutionProcessor(10); + + /* Check Delivery Status */ + DeliveryStatus = APICRead(APIC_ICR0) & APIC_ICR0_DS; + + j++; + } while ((DeliveryStatus) && (j < 1000)); + + KeStallExecutionProcessor(200); + + /* + * Due to the Pentium erratum 3AP. + */ + if (maxlvt > 3) + { + APICRead(APIC_SIVR); + APICWrite(APIC_ESR, 0); + } + + AcceptStatus = APICRead(APIC_ESR) & APIC_ESR_MASK; + + if (DeliveryStatus || AcceptStatus) + { + break; + } + } + + if (DeliveryStatus) + { + DPRINT("STARTUP IPI for CPU %d was never delivered.\n", Cpu); + } + + if (AcceptStatus) + { + DPRINT("STARTUP IPI for CPU %d was never accepted.\n", Cpu); + } + + if (!(DeliveryStatus || AcceptStatus)) + { + + /* Wait no more than 5 seconds for processor to boot */ + DPRINT("Waiting for 5 seconds for CPU %d to boot\n", Cpu); + + /* Wait no more than 5 seconds */ + for (j = 0; j < 50000; j++) + { + if (CPUMap[Cpu].Flags & CPU_ENABLED) + { + break; + } + KeStallExecutionProcessor(100); + } + } + + if (CPUMap[Cpu].Flags & CPU_ENABLED) + { + DbgPrint("CPU %d is now running\n", Cpu); + } + else + { + DbgPrint("Initialization of CPU %d failed\n", Cpu); + } + +#if 0 + DPRINT("Debug bytes are:\n"); + + for (j = 0; j < 4; j++) + { + DPRINT("0x%08X 0x%08X 0x%08X 0x%08X.\n", + Common->Debug[j*4+0], + Common->Debug[j*4+1], + Common->Debug[j*4+2], + Common->Debug[j*4+3]); + } + +#endif +} + +#endif + /* EOF */ _____
Modified: trunk/reactos/hal/halx86/mp/halinit_mp.c --- trunk/reactos/hal/halx86/mp/halinit_mp.c 2005-03-07 16:37:49 UTC (rev 13867) +++ trunk/reactos/hal/halx86/mp/halinit_mp.c 2005-03-07 16:40:32 UTC (rev 13868) @@ -20,10 +20,34 @@
/* FUNCTIONS ***************************************************************/
+extern BOOLEAN HaliFindSmpConfig(VOID); + +/********************************************************************** *****/ VOID HalpInitPhase0(VOID) + { - HalpInitMPS(); + static BOOLEAN MPSInitialized = FALSE; + + + /* Only initialize MP system once. Once called the first time, + each subsequent call is part of the initialization sequence + for an application processor. */ + + DPRINT("HalpInitPhase0()\n"); + + + if (MPSInitialized) + { + KEBUGCHECK(0); + } + [truncated at 1000 lines; 3147 more skipped]