Added Intel MultiProcessor Specification support

svn path=/trunk/; revision=1789
This commit is contained in:
Casper Hornstrup 2001-04-13 16:12:26 +00:00
parent 33408fe398
commit 94309de6e4
26 changed files with 4234 additions and 276 deletions

View file

@ -1,4 +1,4 @@
# $Id: Makefile,v 1.33 2001/04/11 22:13:21 dwelch Exp $
# $Id: Makefile,v 1.34 2001/04/13 16:12:24 chorns Exp $
#
# ReactOS Operating System
#
@ -11,6 +11,7 @@ PATH_TO_TOP := ..
#
# Include details of the kernel configuration
#
include config
#
@ -56,12 +57,6 @@ all: $(EXE_PREFIX)depends$(EXE_POSTFIX) \
$(EXE_PREFIX)depends$(EXE_POSTFIX): depends.c
$(HOST_CC) -o depends$(EXE_POSTFIX) depends.c
#
# Hardware Abstraction Layer (Hal)
# Defines $(OBJECTS_HAL)
#
include hal/x86/sources
#
# Architecture specific Makefile
# Defines $(OBJECTS_ARCH)
@ -110,7 +105,6 @@ OBJECTS_RTL = \
rtl/memcmp.o
# Kernel (Ke)
# Note: head.o MUST be the first file!!!
OBJECTS_KE = \
ke/apc.o \
ke/bug.o \
@ -451,7 +445,7 @@ $(OBJECTS_PATH)/kd.o: $(OBJECTS_KD)
$(TARGETNAME).coff: $(TARGETNAME).rc ../include/reactos/resource.h
# Note: ke.o MUST be the first file!!!
# Note: arch.o MUST be the first file!!!
OBJECTS := \
$(OBJECTS_PATH)/arch.o \
$(OBJECTS_PATH)/ke.o \
@ -601,6 +595,9 @@ ke/main.o: ke/main.c ../include/reactos/buildno.h
mkconfig$(EXE_SUFFIX): mkconfig.c
$(HOST_CC) -g -o mkconfig$(EXE_SUFFIX) mkconfig.c
config:
$(EXE_PREFIX)mkconfig$(EXE_SUFFIX) include/internal/config.h $(CONFIG)
include/internal/config.h: config mkconfig$(EXE_SUFFIX)
$(EXE_PREFIX)mkconfig$(EXE_SUFFIX) include/internal/config.h$(CONFIG)
@ -617,6 +614,7 @@ endif
.%.d: %.S
$(CC) $(CFLAGS) -M $< | $(EXE_PREFIX)depends$(EXE_POSTFIX) $(@D) $@
.%.d: %.asm
$(NASM_CMD) $< | $(EXE_PREFIX)depends$(EXE_POSTFIX) $(@D) $@
# EOF

View file

@ -1,3 +1,10 @@
#
# Hardware Abstraction Layer (Hal) for x86 systems
#
# Defines $(OBJECTS_HAL)
include hal/x86/sources
OBJECTS_BOOT := ke/i386/multiboot.o
OBJECTS_KE_I386 := \
@ -13,7 +20,7 @@ OBJECTS_KE_I386 := \
ke/i386/v86m.o \
ke/i386/v86m_sup.o \
ke/i386/bios.o \
ke/i386/i386-mcount.o \
ke/i386/i386-mcount.o \
ke/i386/gdt.o \
ke/i386/idt.o \
ke/i386/ldt.o \

View file

@ -1,9 +1,9 @@
/* $Id: halinit.c,v 1.17 2001/03/16 18:11:21 dwelch Exp $
/* $Id: halinit.c,v 1.18 2001/04/13 16:12:25 chorns Exp $
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* FILE: ntoskrnl/hal/x86/halinit.c
* PURPOSE: Initalize the uniprocessor, x86 hal
* PURPOSE: Initalize the x86 hal
* PROGRAMMER: David Welch (welch@cwcom.net)
* UPDATE HISTORY:
* 11/06/98: Created
@ -12,27 +12,45 @@
/* INCLUDES *****************************************************************/
#include <ddk/ntddk.h>
#include <internal/config.h>
#include <internal/hal/hal.h>
#include <internal/ntoskrnl.h>
#ifdef MP
#include <internal/hal/mps.h>
#endif /* MP */
#define NDEBUG
#include <internal/debug.h>
/* FUNCTIONS ***************************************************************/
BOOLEAN STDCALL
HalInitSystem (ULONG BootPhase,
PLOADER_PARAMETER_BLOCK LoaderBlock)
HalInitSystem (ULONG BootPhase,
PLOADER_PARAMETER_BLOCK LoaderBlock)
{
if (BootPhase == 0)
{
HalInitializeDisplay (LoaderBlock);
HalpInitPICs ();
#ifdef MP
HalpInitMPS();
#else
HalpInitPICs();
/* Setup busy waiting */
HalpCalibrateStallExecution();
#endif /* MP */
}
else
{
HalpInitBusHandlers ();
}
return TRUE;

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,76 @@
/* $Id: mps.S,v 1.1 2001/04/13 16:12:25 chorns Exp $
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* FILE: ntoskrnl/hal/x86/mps.S
* PURPOSE: Intel MultiProcessor specification support
* PROGRAMMER: Casper S. Hornstrup (chorns@users.sourceforge.net)
* UPDATE HISTORY:
* Created 12/04/2001
*/
/* INCLUDES ******************************************************************/
#include <internal/i386/segment.h>
/* FUNCTIONS *****************************************************************/
#define BEFORE \
pusha; \
pushl %ds; \
pushl %es; \
pushl %fs; \
pushl %gs; \
movl $(KERNEL_DS), %eax; \
movl %eax, %ds; \
movl %eax, %es; \
movl %eax, %gs; \
movl $(PCR_SELECTOR), %eax; \
movl %eax, %fs;
#define AFTER \
popl %gs; \
popl %fs; \
popl %es; \
popl %ds; \
popa;
.globl _MpsTimerInterrupt
_MpsTimerInterrupt:
/* Save registers */
BEFORE
/* Call the C handler */
call _MpsTimerHandler
/* Return to the caller */
AFTER
iret
.globl _MpsErrorInterrupt
_MpsErrorInterrupt:
/* Save registers */
BEFORE
/* Call the C handler */
call _MpsErrorHandler
/* Return to the caller */
AFTER
iret
.globl _MpsSpuriousInterrupt
_MpsSpuriousInterrupt:
/* Save registers */
BEFORE
/* Call the C handler */
call _MpsSpuriousHandler
/* Return to the caller */
AFTER
iret
/* EOF */

View file

@ -0,0 +1,106 @@
;
; COPYRIGHT: See COPYING in the top level directory
; PROJECT: ReactOS kernel
; FILE: ntoskrnl/hal/x86/mpsboot.c
; PURPOSE: Bootstrap code for application processors
; PROGRAMMER: Casper S. Hornstrup (chorns@users.sourceforge.net)
; UPDATE HISTORY:
; Created 12/04/2001
;
;
; Memory map at this stage is:
; 0x2000 Location of our stack
; 0x3000 Startup code for the APs (this code)
;
;
; Base address of common area for BSP and APs
;
LOAD_BASE equ 00200000h
;
; Magic value to be put in EAX when multiboot.S is called as part of the
; application processor initialization process
;
AP_MAGIC equ 12481020h
;
; Segment selectors
;
%define KERNEL_CS (0x8)
%define KERNEL_DS (0x10)
section .text
global _APstart
global _APend
; 16 bit code
BITS 16
_APstart:
cli ; Just in case
xor ax, ax
mov ds, ax
mov ss, ax
mov eax, 3000h + APgdt - _APstart
lgdt [eax]
mov eax, cr0
or eax, 00010001h ; Turn on protected mode and write protection
mov cr0, eax
db 0eah
dw 3000h + flush - _APstart, KERNEL_CS
; 32 bit code
BITS 32
flush:
mov ax, KERNEL_DS
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
mov ss, ax
; Setup a stack for the AP
mov eax, 2000h
mov eax, [eax]
mov esp, eax
; Jump to start of the kernel with AP magic in eax
mov eax, AP_MAGIC
jmp dword KERNEL_CS:(LOAD_BASE + 0x1000)
; Never get here
; Temporary GDT descriptor for the APs
APgdt:
; Limit
dw (3*8)-1
; Base
dd 3000h + gdt - _APstart
gdt:
dw 0x0 ; Null descriptor
dw 0x0
dw 0x0
dw 0x0
dw 0xffff ; Kernel code descriptor
dw 0x0000
dw 0x9a00
dw 0x00cf
dw 0xffff ; Kernel data descriptor
dw 0x0000
dw 0x9200
dw 0x00cf
_APend:

View file

@ -0,0 +1,426 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* FILE: ntoskrnl/hal/x86/mpsirql.c
* PURPOSE: Implements IRQLs for multiprocessor systems
* PROGRAMMERS: David Welch (welch@cwcom.net)
* Casper S. Hornstrup (chorns@users.sourceforge.net)
* UPDATE HISTORY:
* 12/04/2001 CSH Created
*/
/* INCLUDES *****************************************************************/
#include <ddk/ntddk.h>
#include <internal/bitops.h>
#include <internal/ke.h>
#include <internal/ps.h>
#include <internal/hal/mps.h>
#define NDEBUG
#include <internal/debug.h>
/* GLOBALS ******************************************************************/
extern ULONG DpcQueueSize;
static VOID KeSetCurrentIrql(KIRQL newlvl);
/* FUNCTIONS ****************************************************************/
#define IRQL2TPR(irql) (APIC_TPR_MIN + ((irql - DISPATCH_LEVEL - 1) << 4))
static VOID HiSetCurrentPriority(
ULONG Priority)
{
// DPRINT(" P(0x%X) \n", Priority);
APICWrite(APIC_TPR, Priority & APIC_TPR_PRI);
}
static VOID HiSwitchIrql(KIRQL OldIrql, ULONG Flags)
/*
* FUNCTION: Switches to the current irql
* NOTE: Must be called with interrupt disabled
*/
{
PKTHREAD CurrentThread;
KIRQL CurrentIrql;
CurrentIrql = KeGetCurrentKPCR()->Irql;
if (CurrentIrql == HIGH_LEVEL)
{
/* Block all interrupts */
HiSetCurrentPriority(APIC_TPR_MAX);
return;
}
if (CurrentIrql == IPI_LEVEL)
{
HiSetCurrentPriority(APIC_TPR_MAX - 16);
popfl(Flags);
return;
}
if (CurrentIrql == CLOCK2_LEVEL)
{
HiSetCurrentPriority(APIC_TPR_MAX - 32);
popfl(Flags);
return;
}
if (CurrentIrql > DISPATCH_LEVEL)
{
HiSetCurrentPriority(IRQL2TPR(CurrentIrql));
popfl(Flags);
return;
}
/* Pass all interrupts */
HiSetCurrentPriority(0);
if (CurrentIrql == DISPATCH_LEVEL)
{
popfl(Flags);
return;
}
if (CurrentIrql == APC_LEVEL)
{
if (DpcQueueSize > 0 )
{
KeSetCurrentIrql(DISPATCH_LEVEL);
__asm__("sti\n\t");
KiDispatchInterrupt();
__asm__("cli\n\t");
KeSetCurrentIrql(PASSIVE_LEVEL);
}
popfl(Flags);
return;
}
CurrentThread = KeGetCurrentThread();
if (CurrentIrql == PASSIVE_LEVEL &&
CurrentThread != NULL &&
CurrentThread->ApcState.KernelApcPending)
{
KeSetCurrentIrql(APC_LEVEL);
__asm__("sti\n\t");
KiDeliverApc(0, 0, 0);
__asm__("cli\n\t");
KeSetCurrentIrql(PASSIVE_LEVEL);
popfl(Flags);
}
else
{
popfl(Flags);
}
}
KIRQL STDCALL KeGetCurrentIrql (VOID)
/*
* PURPOSE: Returns the current irq level
* RETURNS: The current irq level
*/
{
return(KeGetCurrentKPCR()->Irql);
}
static VOID KeSetCurrentIrql(KIRQL newlvl)
/*
* PURPOSE: Sets the current irq level without taking any action
*/
{
// DPRINT("KeSetCurrentIrql(newlvl %x)\n",newlvl);
KeGetCurrentKPCR()->Irql = newlvl;
}
/**********************************************************************
* NAME EXPORTED
* KfLowerIrql
*
* DESCRIPTION
* Restores the irq level on the current processor
*
* ARGUMENTS
* NewIrql = Irql to lower to
*
* RETURN VALUE
* None
*
* NOTES
* Uses fastcall convention
*/
VOID FASTCALL
KfLowerIrql (
KIRQL NewIrql
)
{
KIRQL CurrentIrql;
KIRQL OldIrql;
ULONG Flags;
//DPRINT("KfLowerIrql(NewIrql %d)\n", NewIrql);
//DbgPrint("KfLowerIrql(NewIrql %d)\n", NewIrql);
//KeBugCheck(0);
pushfl(Flags);
__asm__ ("\n\tcli\n\t");
CurrentIrql = KeGetCurrentKPCR()->Irql;
if (NewIrql > CurrentIrql)
{
DbgPrint ("(%s:%d) NewIrql %x CurrentIrql %x\n",
__FILE__, __LINE__, NewIrql, CurrentIrql);
KeDumpStackFrames (0, 32);
for(;;);
}
OldIrql = CurrentIrql;
KeGetCurrentKPCR()->Irql = NewIrql;
HiSwitchIrql(OldIrql, Flags);
}
/**********************************************************************
* NAME EXPORTED
* KeLowerIrql
*
* DESCRIPTION
* Restores the irq level on the current processor
*
* ARGUMENTS
* NewIrql = Irql to lower to
*
* RETURN VALUE
* None
*
* NOTES
*/
VOID
STDCALL
KeLowerIrql (
KIRQL NewIrql
)
{
KfLowerIrql (NewIrql);
}
/**********************************************************************
* NAME EXPORTED
* KfRaiseIrql
*
* DESCRIPTION
* Raises the hardware priority (irql)
*
* ARGUMENTS
* NewIrql = Irql to raise to
*
* RETURN VALUE
* previous irq level
*
* NOTES
* Uses fastcall convention
*/
KIRQL
FASTCALL
KfRaiseIrql (
KIRQL NewIrql
)
{
KIRQL CurrentIrql;
KIRQL OldIrql;
ULONG Flags;
//DPRINT("KfRaiseIrql(NewIrql %d)\n", NewIrql);
//DbgPrint("KfRaiseIrql(NewIrql %d)\n", NewIrql);
//KeBugCheck(0);
pushfl(Flags);
__asm__ ("\n\tcli\n\t");
CurrentIrql = KeGetCurrentKPCR()->Irql;
if (NewIrql < CurrentIrql)
{
DbgPrint ("%s:%d CurrentIrql %x NewIrql %x\n",
__FILE__,__LINE__,CurrentIrql,NewIrql);
KeBugCheck (0);
for(;;);
}
OldIrql = CurrentIrql;
KeGetCurrentKPCR()->Irql = NewIrql;
//DPRINT("NewIrql %x OldIrql %x\n", NewIrql, OldIrql);
HiSwitchIrql(OldIrql, Flags);
return OldIrql;
}
/**********************************************************************
* NAME EXPORTED
* KeRaiseIrql
*
* DESCRIPTION
* Raises the hardware priority (irql)
*
* ARGUMENTS
* NewIrql = Irql to raise to
* OldIrql (OUT) = Caller supplied storage for the previous irql
*
* RETURN VALUE
* None
*
* NOTES
* Calls KfRaiseIrql
*/
VOID
STDCALL
KeRaiseIrql (
KIRQL NewIrql,
PKIRQL OldIrql
)
{
*OldIrql = KfRaiseIrql (NewIrql);
}
/**********************************************************************
* NAME EXPORTED
* KeRaiseIrqlToDpcLevel
*
* DESCRIPTION
* Raises the hardware priority (irql) to DISPATCH level
*
* ARGUMENTS
* None
*
* RETURN VALUE
* Previous irq level
*
* NOTES
* Calls KfRaiseIrql
*/
KIRQL
STDCALL
KeRaiseIrqlToDpcLevel (VOID)
{
return KfRaiseIrql (DISPATCH_LEVEL);
}
/**********************************************************************
* NAME EXPORTED
* KeRaiseIrqlToSynchLevel
*
* DESCRIPTION
* Raises the hardware priority (irql) to CLOCK2 level
*
* ARGUMENTS
* None
*
* RETURN VALUE
* Previous irq level
*
* NOTES
* Calls KfRaiseIrql
*/
KIRQL
STDCALL
KeRaiseIrqlToSynchLevel (VOID)
{
return KfRaiseIrql (CLOCK2_LEVEL);
}
BOOLEAN STDCALL HalBeginSystemInterrupt (ULONG Vector,
KIRQL Irql,
PKIRQL OldIrql)
{
DPRINT("Vector (0x%X) Irql (0x%X)\n",
Vector, Irql);
if (Vector < FIRST_DEVICE_VECTOR ||
Vector > FIRST_DEVICE_VECTOR + NUMBER_DEVICE_VECTORS) {
DPRINT("Not a device interrupt\n");
return FALSE;
}
/*
* Acknowledge the interrupt
*/
APICSendEOI();
*OldIrql = KeGetCurrentIrql();
KeSetCurrentIrql(Irql);
return TRUE;
}
VOID STDCALL HalEndSystemInterrupt (KIRQL Irql,
ULONG Unknown2)
{
KeSetCurrentIrql(Irql);
}
BOOLEAN STDCALL HalDisableSystemInterrupt (ULONG Vector,
ULONG Unknown2)
{
ULONG irq;
DPRINT("Vector (0x%X)\n", Vector);
if (Vector < FIRST_DEVICE_VECTOR ||
Vector > FIRST_DEVICE_VECTOR + NUMBER_DEVICE_VECTORS) {
DPRINT("Not a device interrupt\n");
return FALSE;
}
irq = VECTOR2IRQ(Vector);
IOAPICMaskIrq(0, irq);
return TRUE;
}
BOOLEAN STDCALL HalEnableSystemInterrupt (ULONG Vector,
ULONG Unknown2,
ULONG Unknown3)
{
ULONG irq;
DPRINT("Vector (0x%X)\n", Vector);
if (Vector < FIRST_DEVICE_VECTOR ||
Vector > FIRST_DEVICE_VECTOR + NUMBER_DEVICE_VECTORS) {
DPRINT("Not a device interrupt\n");
return FALSE;
}
irq = VECTOR2IRQ(Vector);
IOAPICUnmaskIrq(0, irq);
return TRUE;
}
/* EOF */

View file

@ -1,4 +1,4 @@
OBJECTS_HAL = \
OBJECTS_HAL_COMMON = \
hal/x86/adapter.o \
hal/x86/beep.o \
hal/x86/bios32.o \
@ -9,7 +9,6 @@ OBJECTS_HAL = \
hal/x86/fmutex.o \
hal/x86/halinit.o \
hal/x86/isa.o \
hal/x86/irql.o \
hal/x86/kdbg.o \
hal/x86/mbr.o \
hal/x86/misc.o \
@ -24,3 +23,17 @@ OBJECTS_HAL = \
hal/x86/sysinfo.o \
hal/x86/time.o \
hal/x86/udelay.o
OBJECTS_HAL_UP = \
hal/x86/irql.o
OBJECTS_HAL_MP = \
hal/x86/mps.o \
hal/x86/mpsboot.o \
hal/x86/mpsirql.o
ifeq ($(MP), 1)
OBJECTS_HAL = $(OBJECTS_HAL_COMMON) $(OBJECTS_HAL_MP)
else
OBJECTS_HAL = $(OBJECTS_HAL_COMMON) $(OBJECTS_HAL_UP)
endif

View file

@ -10,6 +10,7 @@
#include <ddk/ntddk.h>
#include <string.h>
#include <internal/hal/mps.h>
#define NDEBUG
#include <internal/debug.h>
@ -38,13 +39,15 @@ static BYTE
HalQueryCMOS (BYTE Reg)
{
BYTE Val;
ULONG Flags;
Reg |= 0x80;
pushfl(Flags);
__asm__("cli\n"); // AP unsure as to whether to do this here
WRITE_PORT_UCHAR((PUCHAR)0x70, Reg);
Val = READ_PORT_UCHAR((PUCHAR)0x71);
WRITE_PORT_UCHAR((PUCHAR)0x70, 0);
__asm__("sti\n"); // AP unsure about this too..
popfl(Flags);
return(Val);
}
@ -53,12 +56,15 @@ HalQueryCMOS (BYTE Reg)
static VOID
HalSetCMOS (BYTE Reg, BYTE Val)
{
ULONG Flags;
Reg |= 0x80;
pushfl(Flags);
__asm__("cli\n"); // AP unsure as to whether to do this here
WRITE_PORT_UCHAR((PUCHAR)0x70, Reg);
WRITE_PORT_UCHAR((PUCHAR)0x71, Val);
WRITE_PORT_UCHAR((PUCHAR)0x70, 0);
__asm__("sti\n"); // AP unsure about this too..
popfl(Flags);
}

View file

@ -20,7 +20,7 @@
* MA 02139, USA.
*
*/
/* $Id: udelay.c,v 1.7 2001/03/16 18:11:21 dwelch Exp $
/* $Id: udelay.c,v 1.8 2001/04/13 16:12:25 chorns Exp $
*
* PROJECT: ReactOS kernel
* FILE: ntoskrnl/hal/x86/udelay.c
@ -34,7 +34,7 @@
#include <ddk/ntddk.h>
#define NDEBUG
//#define NDEBUG
#include <internal/debug.h>
/* GLOBALS ******************************************************************/
@ -77,6 +77,8 @@ static unsigned int delay_count = 1;
#define TMR_CH1 0x4 /* Channel 1 bit */
#define TMR_CH0 0x2 /* Channel 0 bit */
static BOOLEAN UdelayCalibrated = FALSE;
/* FUNCTIONS **************************************************************/
void init_pit(float h, unsigned char channel)
@ -98,7 +100,7 @@ void init_pit(float h, unsigned char channel)
VOID STDCALL
__KeStallExecutionProcessor(ULONG Loops)
{
unsigned int i;
register unsigned int i;
for (i=0; i<Loops;i++);
}
@ -108,74 +110,107 @@ VOID STDCALL KeStallExecutionProcessor(ULONG Microseconds)
}
#define HZ (100)
#define CLOCK_TICK_RATE (1193180)
#define LATCH ((CLOCK_TICK_RATE + HZ/2) / HZ)
#define CLOCK_TICK_RATE (1193182)
#define LATCH (CLOCK_TICK_RATE / HZ)
static ULONG Read8254Timer(VOID)
{
ULONG Count;
WRITE_PORT_UCHAR((PUCHAR)0x43, 0x00);
Count = READ_PORT_UCHAR((PUCHAR)0x40);
Count |= READ_PORT_UCHAR((PUCHAR)0x40) << 8;
return Count;
}
static VOID WaitFor8254Wraparound(VOID)
{
ULONG CurCount, PrevCount = ~0;
LONG Delta;
CurCount = Read8254Timer();
do {
PrevCount = CurCount;
CurCount = Read8254Timer();
Delta = CurCount - PrevCount;
/*
* This limit for delta seems arbitrary, but it isn't, it's
* slightly above the level of error a buggy Mercury/Neptune
* chipset timer can cause.
*/
} while (Delta < 300);
}
VOID HalpCalibrateStallExecution(VOID)
{
unsigned int prevtick;
unsigned int i;
unsigned int calib_bit;
extern volatile ULONG KiRawTicks;
ULONG i;
ULONG calib_bit;
ULONG CurCount;
if (UdelayCalibrated)
return;
UdelayCalibrated = TRUE;
DbgPrint("Calibrating delay loop... [");
/* Initialise timer interrupt with MILLISECOND ms interval */
//init_pit(FREQ, 0);
WRITE_PORT_UCHAR((PUCHAR)0x43, 0x34); /* binary, mode 2, LSB/MSB, ch 0 */
WRITE_PORT_UCHAR((PUCHAR)0x40, LATCH & 0xff); /* LSB */
WRITE_PORT_UCHAR((PUCHAR)0x40, LATCH >> 8); /* MSB */
/* Stage 1: Coarse calibration */
WaitFor8254Wraparound();
delay_count = 1;
do {
delay_count <<= 1; /* Next delay count to try */
prevtick=KiRawTicks; /* Wait for the start of the next */
while(prevtick==KiRawTicks); /* timer tick */
prevtick=KiRawTicks; /* Start measurement now */
__KeStallExecutionProcessor(delay_count); /* Do the delay */
} while(prevtick == KiRawTicks); /* Until delay is just too big */
delay_count <<= 1; /* Next delay count to try */
WaitFor8254Wraparound();
__KeStallExecutionProcessor(delay_count); /* Do the delay */
CurCount = Read8254Timer();
} while (CurCount > LATCH / 2);
delay_count >>= 1; /* Get bottom value for delay */
/* Stage 2: Fine calibration */
DbgPrint("delay_count: %d", delay_count);
calib_bit = delay_count; /* Which bit are we going to test */
for(i=0;i<PRECISION;i++) {
calib_bit >>= 1; /* Next bit to calibrate */
if(!calib_bit) break; /* If we have done all bits, stop */
delay_count |= calib_bit; /* Set the bit in delay_count */
prevtick=KiRawTicks; /* Wait for the start of the next */
while(prevtick==KiRawTicks); /* timer tick */
prevtick=KiRawTicks; /* Start measurement now */
__KeStallExecutionProcessor(delay_count); /* Do the delay */
if(prevtick != KiRawTicks) /* If a tick has passed, turn the */
delay_count &= ~calib_bit; /* calibrated bit back off */
calib_bit >>= 1; /* Next bit to calibrate */
if(!calib_bit) break; /* If we have done all bits, stop */
delay_count |= calib_bit; /* Set the bit in delay_count */
WaitFor8254Wraparound();
__KeStallExecutionProcessor(delay_count); /* Do the delay */
CurCount = Read8254Timer();
if (CurCount <= LATCH / 2) /* If a tick has passed, turn the */
delay_count &= ~calib_bit; /* calibrated bit back off */
}
/* We're finished: Do the finishing touches */
delay_count /= MILLISEC; /* Calculate delay_count for 1ms */
delay_count /= (MILLISEC / 2); /* Calculate delay_count for 1ms */
DbgPrint("]\n");
DbgPrint("delay_count: %d\n", delay_count);
DbgPrint("CPU speed: %d\n", delay_count/500);
DbgPrint("CPU speed: %d\n", delay_count/250);
#if 0
DbgPrint("About to start delay loop test\n");
for (i = 0; i < (10*1000*20); i++)
{
KeStallExecutionProcessor(50);
}
DbgPrint("Waiting for five minutes...");
KeStallExecutionProcessor(5*60*1000*1000);
for (i = 0; i < (5*60*1000*20); i++)
{
KeStallExecutionProcessor(50);

View file

@ -0,0 +1,432 @@
#ifndef __INCLUDE_HAL_MPS
#define __INCLUDE_HAL_MPS
#define APIC_DEFAULT_BASE 0xFEE00000 /* Default Local APIC Base Register Address */
#define IOAPIC_DEFAULT_BASE 0xFEC00000 /* Default I/O APIC Base Register Address */
/* APIC Register Address Map */
#define APIC_ID 0x0020 /* Local APIC ID Register (R/W) */
#define APIC_VER 0x0030 /* Local APIC Version Register (R) */
#define APIC_TPR 0x0080 /* Task Priority Register (R/W) */
#define APIC_APR 0x0090 /* Arbitration Priority Register (R) */
#define APIC_PPR 0x00A0 /* Processor Priority Register (R) */
#define APIC_EOI 0x00B0 /* EOI Register (W) */
#define APIC_LDR 0x00D0 /* Logical Destination Register (R/W) */
#define APIC_DFR 0x00E0 /* Destination Format Register (0-27 R, 28-31 R/W) */
#define APIC_SIVR 0x00F0 /* Spurious Interrupt Vector Register (0-3 R, 4-9 R/W) */
#define APIC_ISR 0x0100 /* Interrupt Service Register 0-255 (R) */
#define APIC_TMR 0x0180 /* Trigger Mode Register 0-255 (R) */
#define APIC_IRR 0x0200 /* Interrupt Request Register 0-255 (r) */
#define APIC_ESR 0x0280 /* Error Status Register (R) */
#define APIC_ICR0 0x0300 /* Interrupt Command Register 0-31 (R/W) */
#define APIC_ICR1 0x0310 /* Interrupt Command Register 32-63 (R/W) */
#define APIC_LVTT 0x0320 /* Local Vector Table (Timer) (R/W) */
#define APIC_LVTPC 0x0340 /* Performance Counter LVT (R/W) */
#define APIC_LINT0 0x0350 /* Local Vector Table (LINT0) (R/W) */
#define APIC_LINT1 0x0360 /* Local Vector Table (LINT1) (R/W) */
#define APIC_LVT3 0x0370 /* Local Vector Table (Error) (R/W) */
#define APIC_ICRT 0x0380 /* Initial Count Register for Timer (R/W) */
#define APIC_CCRT 0x0390 /* Current Count Register for Timer (R) */
#define APIC_TDCR 0x03E0 /* Timer Divide Configuration Register (R/W) */
#define APIC_ID_MASK (0xF << 24)
#define GET_APIC_ID(x) (((x) & APIC_ID_MASK) >> 24)
#define APIC_VER_MASK 0xFF00FF
#define GET_APIC_VERSION(x)((x) & 0xFF)
#define GET_APIC_MAXLVT(x) (((x) >> 16) & 0xFF)
#define APIC_TPR_PRI 0xFF
#define APIC_TPR_INT 0xF0
#define APIC_TPR_SUB 0xF
#define APIC_TPR_MAX 0xFF /* Maximum priority */
#define APIC_TPR_MIN 0x20 /* Minimum priority */
#define APIC_LDR_MASK (0xFF << 24)
#define APIC_SIVR_ENABLE (0x1 << 8)
#define APIC_SIVR_FOCUS (0x1 << 9)
#define APIC_ESR_MASK (0xFE << 0) /* Error Mask */
#define APIC_ICR0_VECTOR (0xFF << 0) /* Vector */
#define APIC_ICR0_DM (0x7 << 8) /* Delivery Mode */
#define APIC_ICR0_DESTM (0x1 << 11) /* Destination Mode */
#define APIC_ICR0_DS (0x1 << 12) /* Delivery Status */
#define APIC_ICR0_LEVEL (0x1 << 14) /* Level */
#define APIC_ICR0_TM (0x1 << 15) /* Trigger Mode */
#define APIC_ICR0_DESTS (0x3 << 18) /* Destination Shorthand */
/* Delivery Modes */
#define APIC_DM_FIXED (0x0 << 8)
#define APIC_DM_LOWEST (0x1 << 8)
#define APIC_DM_SMI (0x2 << 8)
#define APIC_DM_REMRD (0x3 << 8)
#define APIC_DM_NMI (0x4 << 8)
#define APIC_DM_INIT (0x5 << 8)
#define APIC_DM_STARTUP (0x6 << 8)
#define APIC_DM_EXTINT (0x7 << 8)
#define GET_APIC_DELIVERY_MODE(x) (((x) >> 8) & 0x7)
#define SET_APIC_DELIVERY_MODE(x,y) (((x) & ~0x700) | ((y) << 8))
/* Destination Shorthand values */
#define APIC_ICR0_DESTS_FIELD (0x0 << 0)
#define APIC_ICR0_DESTS_SELF (0x1 << 18)
#define APIC_ICR0_DESTS_ALL (0x2 << 18)
#define APIC_ICR0_DESTS_ALL_BUT_SELF (0x3 << 18)
#define APIC_ICR0_LEVEL_DEASSERT (0x0 << 14) /* Deassert level */
#define APIC_ICR0_LEVEL_ASSERT (0x1 << 14) /* Assert level */
#define GET_APIC_DEST_FIELD(x) (((x) >> 24) & 0xFF)
#define SET_APIC_DEST_FIELD(x) (((x) & 0xFF) << 24)
#define GET_APIC_TIMER_BASE(x) (((x) >> 18) & 0x3)
#define SET_APIC_TIMER_BASE(x) ((x) << 18)
#define APIC_TIMER_BASE_CLKIN 0x0
#define APIC_TIMER_BASE_TMBASE 0x1
#define APIC_TIMER_BASE_DIV 0x2
#define APIC_LVT_VECTOR (0xFF << 0) /* Vector */
#define APIC_LVT_DS (0x1 << 12) /* Delivery Status */
#define APIC_LVT_REMOTE_IRR (0x1 << 14) /* Remote IRR */
#define APIC_LVT_LEVEL_TRIGGER (0x1 << 15) /* Lvel Triggered */
#define APIC_LVT_MASKED (0x1 << 16) /* Mask */
#define APIC_LVT_PERIODIC (0x1 << 17) /* Timer Mode */
#define APIC_LVT3_DM (0x7 << 8)
#define APIC_LVT3_IIPP (0x1 << 13)
#define APIC_LVT3_TM (0x1 << 15)
#define APIC_LVT3_MASKED (0x1 << 16)
#define APIC_LVT3_OS (0x1 << 17)
#define APIC_TDCR_TMBASE (0x1 << 2)
#define APIC_TDCR_MASK 0x0F
#define APIC_TDCR_2 0x00
#define APIC_TDCR_4 0x01
#define APIC_TDCR_8 0x02
#define APIC_TDCR_16 0x03
#define APIC_TDCR_32 0x08
#define APIC_TDCR_64 0x09
#define APIC_TDCR_128 0x0A
#define APIC_TDCR_1 0x0B
#define APIC_TARGET_SELF 0x100
#define APIC_TARGET_ALL 0x200
#define APIC_TARGET_ALL_BUT_SELF 0x300
#define IPI_CACHE_FLUSH 0x40
#define IPI_INV_TLB 0x41
#define IPI_INV_PTE 0x42
#define IPI_INV_RESCHED 0x43
#define IPI_STOP 0x44
#define APIC_INTEGRATED(version) (version & 0xF0)
/* 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;
/*
* Local APIC timer IRQ vector is on a different priority level,
* to work around the 'lost local interrupt if more than 2 IRQ
* sources per level' errata.
*/
#define LOCAL_TIMER_VECTOR 0xEF
#define CALL_FUNCTION_VECTOR 0xFB
#define RESCHEDULE_VECTOR 0xFC
#define INVALIDATE_TLB_VECTOR 0xFD
#define ERROR_VECTOR 0xFE
#define SPURIOUS_VECTOR 0xFF /* Must be 0xXF */
/*
* First APIC vector available to drivers: (vectors 0x30-0xEE)
* we start at 0x31 to spread out vectors evenly between priority
* levels.
*/
#define FIRST_DEVICE_VECTOR 0x31
#define FIRST_SYSTEM_VECTOR 0xEF
#define NUMBER_DEVICE_VECTORS (FIRST_SYSTEM_VECTOR - FIRST_DEVICE_VECTOR)
/* MP Floating Pointer Structure */
#define MPF_SIGNATURE (('_' << 24) | ('P' << 16) | ('M' << 8) | '_')
typedef struct __attribute__((packed)) _MP_FLOATING_POINTER
{
ULONG Signature[4]; /* _MP_ */
ULONG Address; /* Physical Address Pointer (0 means no configuration table exist) */
UCHAR Length; /* Structure length in 16-byte paragraphs */
UCHAR Specification; /* Specification revision */
UCHAR Checksum; /* Checksum */
UCHAR Feature1; /* MP System Configuration Type */
UCHAR Feature2; /* Bit 7 set for IMCR|PIC */
UCHAR Feature3; /* Unused (0) */
UCHAR Feature4; /* Unused (0) */
UCHAR Feature5; /* Unused (0) */
} MP_FLOATING_POINTER, *PMP_FLOATING_POINTER;
#define FEATURE2_IMCRP 0x80
/* MP Configuration Table Header */
#define MPC_SIGNATURE (('P' << 24) | ('M' << 16) | ('C' << 8) | 'P')
typedef struct __attribute__((packed)) _MP_CONFIGURATION_TABLE
{
ULONG Signature[4]; /* PCMP */
USHORT Length; /* Size of configuration table */
CHAR Specification; /* Specification Revision */
CHAR Checksum; /* Checksum */
CHAR Oem[8]; /* OEM ID */
CHAR ProductId[12]; /* Product ID */
ULONG OemTable; /* 0 if not present */
USHORT OemTableSize; /* 0 if not present */
USHORT EntryCount; /* Number of entries */
ULONG LocalAPICAddress; /* Local APIC address */
USHORT ExtTableLength; /* Extended Table Length */
UCHAR ExtTableChecksum; /* Extended Table Checksum */
UCHAR Reserved; /* Reserved */
} MP_CONFIGURATION_TABLE, *PMP_CONFIGURATION_TABLE;
/* MP Configuration Table Entries */
#define MPCTE_PROCESSOR 0 /* One entry per processor */
#define MPCTE_BUS 1 /* One entry per bus */
#define MPCTE_IOAPIC 2 /* One entry per I/O APIC */
#define MPCTE_INTSRC 3 /* One entry per bus interrupt source */
#define MPCTE_LINTSRC 4 /* One entry per system interrupt source */
typedef struct __attribute__((packed)) _MP_CONFIGURATION_PROCESSOR
{
UCHAR Type; /* 0 */
UCHAR ApicId; /* Local APIC ID for the processor */
UCHAR ApicVersion; /* Local APIC version */
UCHAR CpuFlags; /* CPU flags */
ULONG CpuSignature; /* CPU signature */
ULONG FeatureFlags; /* CPUID feature value */
ULONG Reserved[2]; /* Reserved (0) */
} 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 */
UCHAR BusId; /* Bus ID */
UCHAR BusType[6]; /* Bus type */
} MP_CONFIGURATION_BUS, *PMP_CONFIGURATION_BUS;
#define MAX_BUS 32
#define MP_BUS_ISA 1
#define MP_BUS_EISA 2
#define MP_BUS_PCI 3
#define MP_BUS_MCA 4
#define BUSTYPE_EISA "EISA"
#define BUSTYPE_ISA "ISA"
#define BUSTYPE_INTERN "INTERN" /* Internal BUS */
#define BUSTYPE_MCA "MCA"
#define BUSTYPE_VL "VL" /* Local bus */
#define BUSTYPE_PCI "PCI"
#define BUSTYPE_PCMCIA "PCMCIA"
#define BUSTYPE_CBUS "CBUS"
#define BUSTYPE_CBUSII "CBUSII"
#define BUSTYPE_FUTURE "FUTURE"
#define BUSTYPE_MBI "MBI"
#define BUSTYPE_MBII "MBII"
#define BUSTYPE_MPI "MPI"
#define BUSTYPE_MPSA "MPSA"
#define BUSTYPE_NUBUS "NUBUS"
#define BUSTYPE_TC "TC"
#define BUSTYPE_VME "VME"
#define BUSTYPE_XPRESS "XPRESS"
typedef struct __attribute__((packed)) _MP_CONFIGURATION_IOAPIC
{
UCHAR Type; /* 2 */
UCHAR ApicId; /* I/O APIC ID */
UCHAR ApicVersion; /* I/O APIC version */
UCHAR ApicFlags; /* I/O APIC flags */
ULONG ApicAddress; /* I/O APIC base address */
} MP_CONFIGURATION_IOAPIC, *PMP_CONFIGURATION_IOAPIC;
#define MAX_IOAPIC 2
#define MP_IOAPIC_USABLE 0x01
typedef struct __attribute__((packed)) _MP_CONFIGURATION_INTSRC
{
UCHAR Type; /* 3 */
UCHAR IrqType; /* Interrupt type */
USHORT IrqFlag; /* Interrupt flags */
UCHAR SrcBusId; /* Source bus ID */
UCHAR SrcBusIrq; /* Source bus interrupt */
UCHAR DstApicId; /* Destination APIC ID */
UCHAR DstApicInt; /* Destination interrupt */
} MP_CONFIGURATION_INTSRC, *PMP_CONFIGURATION_INTSRC;
#define MAX_IRQ_SOURCE 128
#define INT_VECTORED 0
#define INT_NMI 1
#define INT_SMI 2
#define INT_EXTINT 3
#define IRQDIR_DEFAULT 0
#define IRQDIR_HIGH 1
#define IRQDIR_LOW 3
typedef struct __attribute__((packed)) _MP_CONFIGURATION_INTLOCAL
{
UCHAR Type; /* 4 */
UCHAR IrqType; /* Interrupt type */
USHORT IrqFlag; /* Interrupt flags */
UCHAR SrcBusId; /* Source bus ID */
UCHAR SrcBusIrq; /* Source bus interrupt */
UCHAR DstApicId; /* Destination local APIC ID */
UCHAR DstApicLInt; /* Destination local APIC interrupt */
} MP_CONFIGURATION_INTLOCAL, *PMP_CONFIGURATION_INTLOCAL;
#define MP_APIC_ALL 0xFF
static inline VOID ReadPentiumClock(PULARGE_INTEGER Count)
{
register ULONG nLow;
register ULONG nHigh;
__asm__ __volatile__ ("rdtsc" : "=a" (nLow), "=d" (nHigh));
Count->u.LowPart = nLow;
Count->u.HighPart = nHigh;
}
#define MAX_CPU 32
typedef struct _CPU_INFO
{
UCHAR Flags; /* CPU flags */
UCHAR APICId; /* Local APIC ID */
UCHAR APICVersion; /* Local APIC version */
UCHAR MaxLVT; /* Number of LVT registers */
ULONG BusSpeed; /* BUS speed */
ULONG CoreSpeed; /* Core speed */
UCHAR Padding[16-12]; /* Padding to 16-byte */
} CPU_INFO, *PCPU_INFO;
/* 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 pushfl(x) __asm__ __volatile__("pushfl ; popl %0":"=g" (x): /* no input */)
#define popfl(x) __asm__ __volatile__("pushl %0 ; popfl": /* no output */ :"g" (x):"memory")
#define PIC_IRQS 16
/* Prototypes */
VOID HalpInitMPS(VOID);
volatile ULONG IOAPICRead(ULONG Apic, ULONG Offset);
VOID IOAPICWrite(ULONG Apic, ULONG Offset, ULONG Value);
VOID IOAPICMaskIrq(ULONG Apic, ULONG Irq);
VOID IOAPICUnmaskIrq(ULONG Apic, ULONG Irq);
volatile inline ULONG APICRead(ULONG Offset);
inline VOID APICWrite(ULONG Offset, ULONG Value);
inline VOID APICSendEOI(VOID);
inline ULONG ThisCPU(VOID);
VOID APICSendIPI(ULONG Target,
ULONG DeliveryMode,
ULONG IntNum,
ULONG Level);
/* For debugging */
VOID IOAPICDump(VOID);
VOID APICDump(VOID);
#endif /* __INCLUDE_HAL_MPS */

View file

@ -172,6 +172,7 @@ VOID KeInitDispatcher(VOID);
VOID KeInitializeDispatcher(VOID);
VOID KeInitializeTimerImpl(VOID);
VOID KeInitializeBugCheck(VOID);
VOID Phase1Initialization(PVOID Context);
VOID KeInit1(VOID);
VOID KeInit2(VOID);

View file

@ -27,11 +27,11 @@
/*
* Defines a descriptor as it appears in the processor tables
*/
typedef struct
typedef struct _DESCRIPTOR
{
unsigned int a;
unsigned int b;
} IDT_DESCRIPTOR, GDT_DESCRIPTOR;
ULONG a;
ULONG b;
} __attribute__ ((packed)) IDT_DESCRIPTOR, GDT_DESCRIPTOR;
extern IDT_DESCRIPTOR KiIdt[256];
//extern GDT_DESCRIPTOR KiGdt[256];

View file

@ -40,9 +40,10 @@
#define KPROCESS_PAGE_TABLE_DIRECTORY 0x10
#define KPCR_BASE 0xFFDFF000
#define KPCR_BASE 0xFF000000
#define KPCR_EXCEPTION_LIST 0x0
#define KPCR_SELF 0x18
#define KPCR_CURRENT_THREAD 0x124
#ifndef __ASM__
@ -52,6 +53,10 @@
struct _KTHREAD;
struct _KTRAPFRAME;
/* FIXME: This does not work if we have more than 24 IRQs (ie. more than one I/O APIC) */
#define VECTOR2IRQ(vector) (((vector) - 0x31) / 8)
#define VECTOR2IRQL(vector) (4 + VECTOR2IRQ(vector))
/*
* Processor Control Region
*/
@ -64,11 +69,29 @@ typedef struct _KPCR
PVOID Reserved1; /* 10 */
PVOID ArbitraryUserPointer; /* 14 */
struct _KPCR* Self; /* 18 */
UCHAR Reserved2[0x108]; /* 1C */
UCHAR ProcessorNumber; /* 1C */
KIRQL Irql; /* 1D */
UCHAR Reserved2[0x2]; /* 1E */
PUSHORT IDT; /* 20 */
PUSHORT GDT; /* 24 */
UCHAR Reserved3[0xFC]; /* 28 */
struct _KTHREAD* CurrentThread; /* 124 */
} KPCR, *PKPCR;
} __attribute__((packed)) KPCR, *PKPCR;
#define CURRENT_KPCR ((PKPCR)KPCR_BASE)
static inline PKPCR KeGetCurrentKPCR(VOID)
{
ULONG value;
__asm__ __volatile__ ("movl %%fs:0x18, %0\n\t"
: "=r" (value)
: /* no inputs */
);
return((PKPCR)value);
}
#define CURRENT_KPCR KeGetCurrentKPCR()
#define KeGetCurrentProcessorNumber (KeGetCurrentKPCR()->ProcessorNumber)
extern HANDLE SystemProcessHandle;

View file

@ -1,4 +1,4 @@
/* $Id: cntrller.c,v 1.6 2001/03/26 05:03:54 phreak Exp $
/* $Id: cntrller.c,v 1.7 2001/04/13 16:12:25 chorns Exp $
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
@ -58,9 +58,9 @@ IoAllocateController(PCONTROLLER_OBJECT ControllerObject,
{
PCONTROLLER_QUEUE_ENTRY entry;
IO_ALLOCATION_ACTION Result;
assert(KeGetCurrentIrql() == DISPATCH_LEVEL);
entry =
ExAllocatePoolWithTag(NonPagedPool, sizeof(CONTROLLER_QUEUE_ENTRY),
TAG_CQE);

View file

@ -42,7 +42,7 @@ USHORT KiGdt[11 * 4] =
0x0, 0x0, 0xfa00, 0xcc, /* User CS */
0x0, 0x0, 0xf200, 0xcc, /* User DS */
0x0, 0x0, 0x0, 0x0, /* TSS */
0x1000, 0xf000, 0x92df, 0xff00, /* PCR */
0x1000, 0x0000, 0x9200, 0xff00, /* PCR */
0x1000, 0x0, 0xf200, 0x0, /* TEB */
0x0, 0x0, 0x0, 0x0, /* Reserved */
0x0, 0x0, 0x0, 0x0, /* LDT */

View file

@ -1,4 +1,4 @@
/* $Id: irq.c,v 1.8 2001/03/16 16:05:34 dwelch Exp $
/* $Id: irq.c,v 1.9 2001/04/13 16:12:26 chorns Exp $
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
@ -19,17 +19,114 @@
/* INCLUDES ****************************************************************/
#include <ddk/ntddk.h>
#include <internal/config.h>
#include <internal/ke.h>
#include <internal/ps.h>
#include <internal/i386/segment.h>
#include <internal/pool.h>
#ifdef MP
#include <internal/hal/mps.h>
#endif /* MP */
#define NDEBUG
#include <internal/debug.h>
/* GLOBALS *****************************************************************/
#ifdef MP
#define IRQ_BASE FIRST_DEVICE_VECTOR
#define NR_IRQS 0x100 - 0x30
#define __STR(x) #x
#define STR(x) __STR(x)
#define INT_NAME(intnum) _KiUnexpectedInterrupt##intnum
#define INT_NAME2(intnum) KiUnexpectedInterrupt##intnum
#define BUILD_COMMON_INTERRUPT_HANDLER() \
__asm__( \
"_KiCommonInterrupt:\n\t" \
"cld\n\t" \
"pushl %ds\n\t" \
"pushl %es\n\t" \
"pushl %fs\n\t" \
"pushl %gs\n\t" \
"movl $0xceafbeef,%eax\n\t" \
"pushl %eax\n\t" \
"movl $" STR(KERNEL_DS) ",%eax\n\t" \
"movl %eax,%ds\n\t" \
"movl %eax,%es\n\t" \
"movl $" STR(PCR_SELECTOR) ",%eax\n\t" \
"movl %eax,%fs\n\t" \
"pushl %esp\n\t" \
"pushl %ebx\n\t" \
"call _KiInterruptDispatch\n\t" \
"popl %eax\n\t" \
"popl %eax\n\t" \
"popl %eax\n\t" \
"popl %gs\n\t" \
"popl %fs\n\t" \
"popl %es\n\t" \
"popl %ds\n\t" \
"popa\n\t" \
"iret\n\t");
#define BUILD_INTERRUPT_HANDLER(intnum) \
VOID INT_NAME2(intnum)(VOID); \
__asm__( \
STR(INT_NAME(intnum)) ":\n\t" \
"pusha\n\t" \
"movl $0x" STR(intnum) ",%ebx\n\t" \
"jmp _KiCommonInterrupt");
/* Interrupt handlers and declarations */
#define B(x,y) \
BUILD_INTERRUPT_HANDLER(x##y)
#define B16(x) \
B(x,0) B(x,1) B(x,2) B(x,3) \
B(x,4) B(x,5) B(x,6) B(x,7) \
B(x,8) B(x,9) B(x,A) B(x,B) \
B(x,C) B(x,D) B(x,E) B(x,F)
BUILD_COMMON_INTERRUPT_HANDLER()
B16(3) B16(4) B16(5) B16(6)
B16(7) B16(8) B16(9) B16(A)
B16(B) B16(C) B16(D) B16(E)
B16(F)
#undef B;
#undef B16;
/* Interrupt handler list */
#define L(x,y) \
(ULONG)&##INT_NAME2(x##y)
#define L16(x) \
L(x,0), L(x,1), L(x,2), L(x,3), \
L(x,4), L(x,5), L(x,6), L(x,7), \
L(x,8), L(x,9), L(x,A), L(x,B), \
L(x,C), L(x,D), L(x,E), L(x,F)
static ULONG irq_handler[NR_IRQS] = {
L16(3), L16(4), L16(5), L16(6),
L16(7), L16(8), L16(9), L16(A),
L16(B), L16(C), L16(D), L16(E),
L16(F)
};
#undef L;
#undef L16;
#else /* MP */
#define NR_IRQS (16)
#define IRQ_BASE (0x40)
@ -70,6 +167,8 @@ static unsigned int irq_handler[NR_IRQS]=
(int)&irq_handler_15,
};
#endif /* MP */
/*
* PURPOSE: Object describing each isr
* NOTE: The data in this table is only modified at passsive level but can
@ -91,9 +190,22 @@ static KSPIN_LOCK isr_table_lock = {0,};
VOID KeInitInterrupts (VOID)
{
int i;
DPRINT("KeInitInterrupts ()\n",0);
#ifdef MP
/*
* Setup the IDT entries to point to the interrupt handlers
*/
for (i=0;i<NR_IRQS;i++)
{
KiIdt[0x30+i].a=(irq_handler[i]&0xffff)+(KERNEL_CS<<16);
KiIdt[0x30+i].b=(irq_handler[i]&0xffff0000)+PRESENT+
I486_INTERRUPT_GATE;
InitializeListHead(&isr_table[i]);
}
#else
/*
* Setup the IDT entries to point to the interrupt handlers
*/
@ -104,6 +216,9 @@ VOID KeInitInterrupts (VOID)
I486_INTERRUPT_GATE;
InitializeListHead(&isr_table[i]);
}
#endif
}
typedef struct _KIRQ_TRAPFRAME
@ -125,6 +240,95 @@ typedef struct _KIRQ_TRAPFRAME
ULONG Eflags;
} KIRQ_TRAPFRAME, *PKIRQ_TRAPFRAME;
#ifdef MP
VOID
KiInterruptDispatch (ULONG Vector, PKIRQ_TRAPFRAME Trapframe)
/*
* FUNCTION: Calls the irq specific handler for an irq
* ARGUMENTS:
* Vector = Interrupt vector
* Trapframe = CPU context
*/
{
KIRQL old_level;
PKINTERRUPT isr;
PLIST_ENTRY current;
ULONG irq;
DPRINT("I(%d) ", Vector);
/*
* Notify the rest of the kernel of the raised irq level
*/
HalBeginSystemInterrupt (Vector,
VECTOR2IRQL(Vector),
&old_level);
irq = VECTOR2IRQ(Vector);
/*
* Enable interrupts
* NOTE: Only higher priority interrupts will get through
*/
__asm__("sti\n\t");
DPRINT("KiInterruptDispatch(Vector %d)\n", Vector);
/*
* Iterate the list until one of the isr tells us its device interrupted
*/
current = isr_table[irq].Flink;
isr = CONTAINING_RECORD(current,KINTERRUPT,Entry);
//DPRINT("current %x isr %x\n",current,isr);
while (current!=(&isr_table[irq]) &&
!isr->ServiceRoutine(isr,isr->ServiceContext))
{
current = current->Flink;
isr = CONTAINING_RECORD(current,KINTERRUPT,Entry);
//DPRINT("current %x isr %x\n",current,isr);
}
/*
* Disable interrupts
*/
__asm__("cli\n\t");
/*
* Unmask the related irq
*/
HalEnableSystemInterrupt (Vector, 0, 0);
/*
* If the processor level will drop below dispatch level on return then
* issue a DPC queue drain interrupt
*/
if (old_level < DISPATCH_LEVEL)
{
HalEndSystemInterrupt (DISPATCH_LEVEL, 0);
__asm__("sti\n\t");
if (KeGetCurrentThread() != NULL)
{
KeGetCurrentThread()->LastEip = Trapframe->Eip;
}
KiDispatchInterrupt();
if (KeGetCurrentThread() != NULL &&
KeGetCurrentThread()->Alerted[1] != 0 &&
Trapframe->Cs != KERNEL_CS)
{
HalEndSystemInterrupt (APC_LEVEL, 0);
KiDeliverNormalApc();
}
}
HalEndSystemInterrupt (old_level, 0);
}
#else /* MP */
VOID
KiInterruptDispatch (ULONG irq, PKIRQ_TRAPFRAME Trapframe)
/*
@ -136,16 +340,14 @@ KiInterruptDispatch (ULONG irq, PKIRQ_TRAPFRAME Trapframe)
KIRQL old_level;
PKINTERRUPT isr;
PLIST_ENTRY current;
// DbgPrint("{");
/*
* Notify the rest of the kernel of the raised irq level
*/
HalBeginSystemInterrupt (irq+IRQ_BASE,
HIGH_LEVEL-irq,
&old_level);
/*
* Enable interrupts
* NOTE: Only higher priority interrupts will get through
@ -214,6 +416,7 @@ KiInterruptDispatch (ULONG irq, PKIRQ_TRAPFRAME Trapframe)
HalEndSystemInterrupt (old_level, 0);
}
#endif /* MP */
static VOID
KeDumpIrqList(VOID)

View file

@ -45,42 +45,31 @@ ULONG KiPcrInitDone = 0;
VOID
KeInit1(VOID)
{
PKPCR KPCR;
extern USHORT KiGdt[];
KiCheckFPU();
KeInitExceptions ();
KeInitInterrupts ();
/* Initialize the initial PCR region. We can't allocate a page
with MmAllocPage() here because MmInit1() has not yet been
called, so we use a predefined page in low memory */
KPCR = (PKPCR)KPCR_BASE;
memset(KPCR, 0, PAGESIZE);
KPCR->Self = (PKPCR)KPCR_BASE;
KPCR->Irql = HIGH_LEVEL;
KPCR->GDT = (PUSHORT)&KiGdt;
KPCR->IDT = (PUSHORT)&KiIdt;
KiPcrInitDone = 1;
}
VOID
KeInit2(VOID)
{
PVOID PcrPage;
KeInitDpc();
KeInitializeBugCheck();
KeInitializeDispatcher();
KeInitializeTimerImpl();
/*
* Initialize the PCR region.
* FIXME: This should be per-processor.
*/
PcrPage = MmAllocPage(0);
if (PcrPage == NULL)
{
DPRINT1("No memory for PCR page\n");
KeBugCheck(0);
}
MmCreateVirtualMapping(NULL,
(PVOID)KPCR_BASE,
PAGE_READWRITE,
(ULONG)PcrPage);
memset((PVOID)KPCR_BASE, 0, 4096);
KiPcrInitDone = 1;
}

View file

@ -1,3 +1,4 @@
#include <internal/config.h>
#include <internal/ntoskrnl.h>
#include <internal/i386/segment.h>
@ -8,7 +9,12 @@
#define MULTIBOOT_HEADER_FLAGS (0x00010003)
#define V2P(x) (x - 0xc0000000 + 0x200000)
#ifdef MP
#define AP_MAGIC (0x12481020)
#endif /* MP */
.globl _NtProcessStartup
.globl _start
@ -19,12 +25,15 @@
.globl _unmap_me
.globl _unmap_me2
.globl _unmap_me3
.globl _unmap_me4
/*
* This is called by the realmode loader, with protected mode
* enabled, paging disabled and the segment registers pointing
* a 4Gb, 32-bit segment starting at zero.
*
* EAX = Multiboot magic or application processor magic
*
* EBX = Points to a structure in lowmem with data from the
* loader
*/
@ -65,6 +74,18 @@ _multiboot_entry:
*/
cld
#ifdef MP
/*
* Save the multiboot or application processor magic
*/
movl %eax, %edx
cmpl $AP_MAGIC, %edx
je .m1
#endif /* MP */
/*
* Zero the BSS
*/
@ -87,6 +108,10 @@ _multiboot_entry:
movl $(V2P(kernel_pagetable) + 0x7), 0xC00(%esi)
movl $(V2P(lowmem_pagetable) + 0x7), 0xD00(%esi)
movl $(V2P(startup_pagedirectory) + 0x7), 0xF00(%esi)
#ifdef MP
movl $(V2P(apic_pagetable) + 0x7), 0xFEC(%esi)
#endif /* MP */
movl $(V2P(kpcr_pagetable) + 0x7), 0xFF0(%esi)
/*
* Initialize the page table that maps low memory
@ -114,6 +139,39 @@ _multiboot_entry:
cmpl $2048, %edi
jl .l4
#ifdef MP
/*
* Initialize the page table that maps the APIC register address space
*/
/* FIXME: APIC register address space can be non-standard so do the mapping later */
movl $V2P(apic_pagetable), %esi
movl $0, %edi
movl $0xFEC0001B, %eax
movl %eax, (%esi, %edi)
movl $0x800, %edi
movl $0xFEE0001B, %eax
movl %eax, (%esi, %edi)
#endif /* MP */
/*
* Initialize the page table that maps the initial KPCR (at FF000000)
*/
movl $V2P(kpcr_pagetable), %esi
movl $0, %edi
movl $0x1007, %eax
movl %eax, (%esi, %edi)
#ifdef MP
.m1:
#endif /* MP */
/*
* Set up the PDBR
*/
@ -138,6 +196,9 @@ _multiboot_entry:
* Load the GDTR and IDTR with new tables located above
* 0xc0000000
*/
/* FIXME: Application processors should have their own GDT/IDT */
lgdt _KiGdtDescriptor
lidt _KiIdtDescriptor
@ -147,9 +208,37 @@ _multiboot_entry:
movl $KERNEL_DS, %eax
movl %eax, %ds
movl %eax, %es
movl %eax, %fs
movl %eax, %gs
movl %eax, %ss
movl $PCR_SELECTOR, %eax
movl %eax, %fs
#ifdef MP
cmpl $AP_MAGIC, %edx
jne .m2
/*
* This is an application processor executing
*/
/*
* Initialize EFLAGS
*/
pushl $0
popfl
/*
* Call the application processor initialization code
*/
pushl $0
pushl $KERNEL_CS
pushl $_KiSystemStartup
lret
.m2:
#endif /* MP */
/*
* Load the initial ring0 stack
@ -185,7 +274,15 @@ lowmem_pagetable:
kernel_pagetable:
.fill 4096, 1, 0
#ifdef MP
apic_pagetable:
.fill 4096, 1, 0
#endif /* MP */
kpcr_pagetable:
.fill 4096, 1, 0
_unmap_me:
.fill 4096, 1, 0
@ -202,5 +299,3 @@ _trap_stack_top:
_unmap_me3:
.fill 4096, 1, 0

View file

@ -71,11 +71,17 @@ _Ki386ContextSwitch:
addl $8, %esp
popl %ebx
/*
* Load the PCR selector
*/
movl $PCR_SELECTOR, %eax
movl %eax, %fs
/*
* Set the current thread information in the PCR
*/
movl %ebx, (KPCR_BASE + KPCR_CURRENT_THREAD)
movl %ebx, %fs:KPCR_CURRENT_THREAD
/*
* FIXME: Save debugging state.
*/
@ -97,7 +103,7 @@ _Ki386ContextSwitch:
*/
movl KTHREAD_INITIAL_STACK(%ebx), %eax
movl %eax, (_KiTss + KTSS_ESP0)
/*
* Change the address space
*/
@ -105,12 +111,6 @@ _Ki386ContextSwitch:
movl KPROCESS_PAGE_TABLE_DIRECTORY(%ebx), %eax
movl %eax, %cr3
/*
* Load the PCR selector
*/
movl $PCR_SELECTOR, %eax
movl %eax, %fs
/*
* FIXME: Restore floating point state
*/

View file

@ -16,7 +16,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/* $Id: main.c,v 1.86 2001/04/10 17:48:17 dwelch Exp $
/* $Id: main.c,v 1.87 2001/04/13 16:12:25 chorns Exp $
*
* PROJECT: ReactOS kernel
* FILE: ntoskrnl/ke/main.c
@ -29,6 +29,7 @@
/* INCLUDES *****************************************************************/
#include <ddk/ntddk.h>
#include <internal/config.h>
#include <internal/ntoskrnl.h>
#include <reactos/resource.h>
#include <internal/mm.h>
@ -52,11 +53,15 @@
ULONG EXPORTED NtBuildNumber = KERNEL_VERSION_BUILD;
ULONG EXPORTED NtGlobalFlag = 0;
CHAR EXPORTED KeNumberProcessors = 1;
CHAR EXPORTED KeNumberProcessors;
LOADER_PARAMETER_BLOCK EXPORTED KeLoaderBlock;
static LOADER_MODULE KeLoaderModules[64];
static UCHAR KeLoaderModuleStrings[64][256];
static UCHAR KeLoaderCommandLine[256];
static ULONG FirstKrnlPhysAddr;
static ULONG LastKrnlPhysAddr;
static ULONG LastKernelAddress;
volatile BOOLEAN Initialized = FALSE;
/* FUNCTIONS ****************************************************************/
@ -378,123 +383,193 @@ InitSystemSharedUserPage (PCSZ ParameterLine)
KeBugCheck (0x0);
}
}
#if 0
VOID
TestV86Mode(VOID)
{
ULONG i;
extern UCHAR OrigIVT[1024];
KV86M_REGISTERS regs;
NTSTATUS Status;
struct vesa_info* vi;
for (i = 0; i < (640 / 4); i++)
{
MmCreateVirtualMapping(NULL,
(PVOID)(i * 4096),
PAGE_EXECUTE_READWRITE,
(ULONG)MmAllocPage(0));
}
for (; i < (1024 / 4); i++)
{
MmCreateVirtualMapping(NULL,
(PVOID)(i * 4096),
PAGE_EXECUTE_READ,
i * 4096);
}
vi = (struct vesa_info*)0x20000;
vi->Signature[0] = 'V';
vi->Signature[1] = 'B';
vi->Signature[2] = 'E';
vi->Signature[3] = '2';
memset(&regs, 0, sizeof(regs));
regs.Eax = 0x4F00;
regs.Es = 0x2000;
regs.Edi = 0x0;
memcpy((PVOID)0x0, OrigIVT, 1024);
Status = Ke386CallBios(0x10, &regs);
DbgPrint("Finished (Status %x, CS:EIP %x:%x)\n", Status, regs.Cs,
regs.Eip);
DbgPrint("Eax %x\n", regs.Eax);
DbgPrint("Signature %.4s\n", vi->Signature);
DbgPrint("TotalVideoMemory %dKB\n", vi->TotalVideoMemory * 64);
}
#endif
VOID
_main (ULONG MultiBootMagic, PLOADER_PARAMETER_BLOCK _LoaderBlock)
/*
* FUNCTION: Called by the boot loader to start the kernel
* ARGUMENTS:
* LoaderBlock = Pointer to boot parameters initialized by the boot
* loader
* NOTE: The boot parameters are stored in low memory which will become
* invalid after the memory managment is initialized so we make a local copy.
*/
ExpInitializeExecutive(VOID)
{
ULONG i;
ULONG last_kernel_address;
ULONG start;
PCHAR name;
extern ULONG _bss_end__;
/*
* Copy the parameters to a local buffer because lowmem will go away
*/
memcpy (&KeLoaderBlock, _LoaderBlock, sizeof(LOADER_PARAMETER_BLOCK));
memcpy (&KeLoaderModules[1], (PVOID)KeLoaderBlock.ModsAddr,
sizeof(LOADER_MODULE) * KeLoaderBlock.ModsCount);
KeLoaderBlock.ModsCount++;
KeLoaderBlock.ModsAddr = (ULONG)&KeLoaderModules;
/*
* FIXME: Preliminary hack!!!! Add boot device to beginning of command line.
* This should be done by the boot loader.
*/
strcpy (KeLoaderCommandLine,
"multi(0)disk(0)rdisk(0)partition(1)\\reactos ");
strcat (KeLoaderCommandLine, (PUCHAR)KeLoaderBlock.CommandLine);
KeLoaderBlock.CommandLine = (ULONG)KeLoaderCommandLine;
strcpy(KeLoaderModuleStrings[0], "ntoskrnl.exe");
KeLoaderModules[0].String = (ULONG)KeLoaderModuleStrings[0];
KeLoaderModules[0].ModStart = 0xC0000000;
KeLoaderModules[0].ModEnd = PAGE_ROUND_UP((ULONG)&_bss_end__);
for (i = 1; i < KeLoaderBlock.ModsCount; i++)
{
strcpy(KeLoaderModuleStrings[i], (PUCHAR)KeLoaderModules[i].String);
KeLoaderModules[i].ModStart -= 0x200000;
KeLoaderModules[i].ModStart += 0xc0000000;
KeLoaderModules[i].ModEnd -= 0x200000;
KeLoaderModules[i].ModEnd += 0xc0000000;
KeLoaderModules[i].String = (ULONG)KeLoaderModuleStrings[i];
}
/*
* Initialization phase 0
*/
HalInitSystem (0, (PLOADER_PARAMETER_BLOCK)&KeLoaderBlock);
KeInit1();
LdrInit1();
KeLowerIrql(DISPATCH_LEVEL);
/* Execute executive initialization code on bootstrap processor only */
if (!Initialized)
{
Initialized = TRUE;
DPRINT("Phase 0 initialization started...\n");
/*
* Fail at runtime if someone has changed various structures without
* updating the offsets used for the assembler code.
*/
assert(FIELD_OFFSET(KTHREAD, InitialStack) == KTHREAD_INITIAL_STACK);
assert(FIELD_OFFSET(KTHREAD, Teb) == KTHREAD_TEB);
assert(FIELD_OFFSET(KTHREAD, KernelStack) == KTHREAD_KERNEL_STACK);
assert(FIELD_OFFSET(KTHREAD, PreviousMode) == KTHREAD_PREVIOUS_MODE);
assert(FIELD_OFFSET(KTHREAD, TrapFrame) == KTHREAD_TRAP_FRAME);
assert(FIELD_OFFSET(ETHREAD, ThreadsProcess) == ETHREAD_THREADS_PROCESS);
assert(FIELD_OFFSET(KPROCESS, PageTableDirectory) ==
KPROCESS_PAGE_TABLE_DIRECTORY);
assert(FIELD_OFFSET(KTRAP_FRAME, Reserved9) == KTRAP_FRAME_RESERVED9);
assert(FIELD_OFFSET(KV86M_TRAP_FRAME, regs) == TF_REGS);
assert(FIELD_OFFSET(KV86M_TRAP_FRAME, orig_ebp) == TF_ORIG_EBP);
assert(FIELD_OFFSET(KPCR, ExceptionList) == KPCR_EXCEPTION_LIST);
assert(FIELD_OFFSET(KPCR, Self) == KPCR_SELF);
assert(FIELD_OFFSET(KPCR, CurrentThread) == KPCR_CURRENT_THREAD);
LdrInit1();
KeLowerIrql(DISPATCH_LEVEL);
NtEarlyInitVdm();
MmInit1(FirstKrnlPhysAddr, LastKrnlPhysAddr, LastKernelAddress);
/*
* Initialize the kernel debugger
*/
KdInitSystem (0, (PLOADER_PARAMETER_BLOCK)&KeLoaderBlock);
if (KdPollBreakIn ())
{
DbgBreakPointWithStatus (DBG_STATUS_CONTROL_C);
}
MmInit2();
KeInit2();
{
char tmpbuf[80];
sprintf(tmpbuf,"System with %d/%d MB memory\n",
(unsigned int)(KeLoaderBlock.MemLower)/1024,
(unsigned int)(KeLoaderBlock.MemHigher)/1024);
HalDisplayString(tmpbuf);
}
KeLowerIrql(PASSIVE_LEVEL);
ObInit();
PiInitProcessManager();
/*
* Allow interrupts
*/
__asm__ ("sti\n\t");
#ifdef MP
Phase1Initialization(NULL);
#endif
}
}
VOID
KiSystemStartup(VOID)
{
ExpInitializeExecutive();
for (;;)
{
NtYieldExecution();
}
}
/* Initialization phase 1 */
VOID Phase1Initialization(PVOID Context)
{
ULONG i;
ULONG start;
PCHAR name;
CHAR str[50];
DPRINT("Initialization phase 1 started...\n");
/*
* Display version number and copyright/warranty message
*/
HalDisplayString("Starting ReactOS "KERNEL_VERSION_STR" (Build "
KERNEL_VERSION_BUILD_STR")\n");
KERNEL_VERSION_BUILD_STR")\n");
HalDisplayString(RES_STR_LEGAL_COPYRIGHT);
HalDisplayString("\n\nReactOS is free software, covered by the GNU General "
"Public License, and you\n");
"Public License, and you\n");
HalDisplayString("are welcome to change it and/or distribute copies of it "
"under certain\n");
"under certain\n");
HalDisplayString("conditions. There is absolutely no warranty for ReactOS.\n");
/*
* Fail at runtime if someone has changed various structures without
* updating the offsets used for the assembler code
*/
assert(FIELD_OFFSET(KTHREAD, InitialStack) == KTHREAD_INITIAL_STACK);
assert(FIELD_OFFSET(KTHREAD, Teb) == KTHREAD_TEB);
assert(FIELD_OFFSET(KTHREAD, KernelStack) == KTHREAD_KERNEL_STACK);
assert(FIELD_OFFSET(KTHREAD, PreviousMode) == KTHREAD_PREVIOUS_MODE);
assert(FIELD_OFFSET(KTHREAD, TrapFrame) == KTHREAD_TRAP_FRAME);
assert(FIELD_OFFSET(ETHREAD, ThreadsProcess) == ETHREAD_THREADS_PROCESS);
assert(FIELD_OFFSET(KPROCESS, PageTableDirectory) ==
KPROCESS_PAGE_TABLE_DIRECTORY);
assert(FIELD_OFFSET(KTRAP_FRAME, Reserved9) == KTRAP_FRAME_RESERVED9);
assert(FIELD_OFFSET(KV86M_TRAP_FRAME, regs) == TF_REGS);
assert(FIELD_OFFSET(KV86M_TRAP_FRAME, orig_ebp) == TF_ORIG_EBP);
last_kernel_address = KeLoaderModules[KeLoaderBlock.ModsCount - 1].ModEnd;
NtEarlyInitVdm();
MmInit1(KeLoaderModules[0].ModStart - 0xc0000000 + 0x200000,
last_kernel_address - 0xc0000000 + 0x200000,
last_kernel_address);
/* Initialize all processors */
KeNumberProcessors = 0;
/*
* Initialize the kernel debugger
*/
KdInitSystem (0, (PLOADER_PARAMETER_BLOCK)&KeLoaderBlock);
if (KdPollBreakIn ())
{
DbgBreakPointWithStatus (DBG_STATUS_CONTROL_C);
}
while (!HalAllProcessorsStarted())
{
HalInitializeProcessor(
KeNumberProcessors);
KeNumberProcessors++;
}
/*
* Initialization phase 1
* Initalize various critical subsystems
*/
if (KeNumberProcessors > 1)
{
sprintf(str, "Found %d system processors.\n",
KeNumberProcessors);
}
else
{
strcpy(str, "Found 1 system processor.\n");
}
HalDisplayString(str);
#ifdef MP
DbgPrint("BSP halted\n");
for (;;);
#endif /* MP */
/*
* Initialize various critical subsystems
*/
HalInitSystem (1, (PLOADER_PARAMETER_BLOCK)&KeLoaderBlock);
MmInit2();
KeInit2();
/*
* Allow interrupts
*/
KeLowerIrql(PASSIVE_LEVEL);
ObInit();
PiInitProcessManager();
ExInit();
IoInit();
LdrInitModuleManagement();
@ -542,25 +617,50 @@ _main (ULONG MultiBootMagic, PLOADER_PARAMETER_BLOCK _LoaderBlock)
DPRINT1("process module '%s' at %08lx\n", name, start);
LdrProcessDriver((PVOID)start, name);
}
}
DPRINT("About to try MmAllocateContiguousAlignedMemory\n");
do
{
extern PVOID STDCALL
MmAllocateContiguousAlignedMemory(IN ULONG NumberOfBytes,
IN PHYSICAL_ADDRESS HighestAcceptableAddress,
IN ULONG Alignment);
PVOID v;
PHYSICAL_ADDRESS p;
p.QuadPart = 16*1024*1024;
v = MmAllocateContiguousAlignedMemory(12*1024, p,
64*1024);
if (v != NULL)
{
DPRINT("Worked\n");
}
else
{
DPRINT("Failed\n");
}
}
while (0);
/* Create the SystemRoot symbolic link */
DbgPrint("CommandLine: %s\n", (PUCHAR)KeLoaderBlock.CommandLine);
CreateSystemRootLink ((PUCHAR)KeLoaderBlock.CommandLine);
#ifdef DBGPRINT_FILE_LOG
/* On the assumption that we can now access disks start up the debug
logger thread */
DebugLogInit2();
#endif /* DBGPRINT_FILE_LOG */
CmInitializeRegistry2();
/*
* Load Auto configured drivers
*/
LdrLoadAutoConfigDrivers();
/*
* Assign drive letters
*/
@ -580,9 +680,76 @@ _main (ULONG MultiBootMagic, PLOADER_PARAMETER_BLOCK _LoaderBlock)
*/
LdrLoadInitialProcess();
DbgPrint("Finished main()\n");
DbgPrint("Finished kernel initialization.\n");
/* FIXME: Call zero page thread function */
PsTerminateSystemThread(STATUS_SUCCESS);
}
VOID
_main (ULONG MultiBootMagic, PLOADER_PARAMETER_BLOCK _LoaderBlock)
/*
* FUNCTION: Called by the boot loader to start the kernel
* ARGUMENTS:
* LoaderBlock = Pointer to boot parameters initialized by the boot
* loader
* NOTE: The boot parameters are stored in low memory which will become
* invalid after the memory managment is initialized so we make a local copy.
*/
{
ULONG i;
ULONG last_kernel_address;
extern ULONG _bss_end__;
/*
* Copy the parameters to a local buffer because lowmem will go away
*/
memcpy (&KeLoaderBlock, _LoaderBlock, sizeof(LOADER_PARAMETER_BLOCK));
memcpy (&KeLoaderModules[1], (PVOID)KeLoaderBlock.ModsAddr,
sizeof(LOADER_MODULE) * KeLoaderBlock.ModsCount);
KeLoaderBlock.ModsCount++;
KeLoaderBlock.ModsAddr = (ULONG)&KeLoaderModules;
/*
* FIXME: Preliminary hack!!!! Add boot device to beginning of command line.
* This should be done by the boot loader.
*/
strcpy (KeLoaderCommandLine,
"multi(0)disk(0)rdisk(0)partition(1)\\reactos /DEBUGPORT=SCREEN");
strcat (KeLoaderCommandLine, (PUCHAR)KeLoaderBlock.CommandLine);
KeLoaderBlock.CommandLine = (ULONG)KeLoaderCommandLine;
strcpy(KeLoaderModuleStrings[0], "ntoskrnl.exe");
KeLoaderModules[0].String = (ULONG)KeLoaderModuleStrings[0];
KeLoaderModules[0].ModStart = 0xC0000000;
KeLoaderModules[0].ModEnd = PAGE_ROUND_UP((ULONG)&_bss_end__);
for (i = 1; i < KeLoaderBlock.ModsCount; i++)
{
strcpy(KeLoaderModuleStrings[i], (PUCHAR)KeLoaderModules[i].String);
KeLoaderModules[i].ModStart -= 0x200000;
KeLoaderModules[i].ModStart += 0xc0000000;
KeLoaderModules[i].ModEnd -= 0x200000;
KeLoaderModules[i].ModEnd += 0xc0000000;
KeLoaderModules[i].String = (ULONG)KeLoaderModuleStrings[i];
}
last_kernel_address = KeLoaderModules[KeLoaderBlock.ModsCount - 1].ModEnd;
FirstKrnlPhysAddr = KeLoaderModules[0].ModStart - 0xc0000000 + 0x200000;
LastKrnlPhysAddr = last_kernel_address - 0xc0000000 + 0x200000;
LastKernelAddress = last_kernel_address;
KeInit1();
#if 0
/*
* Allow interrupts
*/
__asm__ ("sti\n\t");
#endif
KiSystemStartup();
}
/* EOF */

View file

@ -1,4 +1,4 @@
/* $Id: timer.c,v 1.43 2001/03/18 19:35:13 dwelch Exp $
/* $Id: timer.c,v 1.44 2001/04/13 16:12:25 chorns Exp $
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
@ -125,7 +125,7 @@ NTSTATUS STDCALL NtDelayExecution(IN ULONG Alertable,
Alertable, Internal, Timeout);
DPRINT("Execution delay is %d/%d\n",
Timeout.u.Highpart, Timeout.u.LowPart);
Timeout.u.HighPart, Timeout.u.LowPart);
Status = KeDelayExecutionThread(UserMode, Alertable, &Timeout);
return(Status);
}
@ -462,17 +462,12 @@ KeInitializeTimerImpl(VOID)
{
TIME_FIELDS TimeFields;
LARGE_INTEGER SystemBootTime;
extern VOID HalpCalibrateStallExecution (VOID);
DPRINT("KeInitializeTimerImpl()\n");
HalpCalibrateStallExecution ();
InitializeListHead(&TimerListHead);
KeInitializeSpinLock(&TimerListLock);
KeInitializeDpc(&ExpireTimerDpc, KeExpireTimers, 0);
TimerInitDone = TRUE;
/*
* Calculate the starting time for the system clock
*/
@ -480,6 +475,6 @@ KeInitializeTimerImpl(VOID)
RtlTimeFieldsToTime(&TimeFields, &SystemBootTime);
boot_time=SystemBootTime.QuadPart;
system_time=boot_time;
DPRINT("Finished KeInitializeTimerImpl()\n");
}

View file

@ -193,7 +193,15 @@ PVOID MmInitializePageList(PVOID FirstPhysKernelAddress,
InsertTailList(&BiosPageListHead,
&MmPageArray[0].ListEntry);
i = 1;
/*
* Page one is reserved for the initial KPCR
*/
MmPageArray[1].Flags = MM_PHYSICAL_PAGE_BIOS;
MmPageArray[1].ReferenceCount = 0;
InsertTailList(&BiosPageListHead,
&MmPageArray[1].ListEntry);
i = 2;
if ((ULONG)FirstPhysKernelAddress < 0xa0000)
{
MmStats.NrFreePages += (((ULONG)FirstPhysKernelAddress/PAGESIZE) - 1);

View file

@ -16,7 +16,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/* $Id: page.c,v 1.25 2001/03/26 20:46:53 dwelch Exp $
/* $Id: page.c,v 1.26 2001/04/13 16:12:26 chorns Exp $
*
* PROJECT: ReactOS kernel
* FILE: ntoskrnl/mm/i386/page.c
@ -589,10 +589,19 @@ MmCreateVirtualMappingUnsafe(PEPROCESS Process,
ULONG flProtect,
ULONG PhysicalAddress)
{
PEPROCESS CurrentProcess = PsGetCurrentProcess();
ULONG Attributes = 0;
PEPROCESS CurrentProcess;
ULONG Attributes;
PULONG Pte;
NTSTATUS Status;
if (Process != NULL)
{
CurrentProcess = PsGetCurrentProcess();
}
else
{
CurrentProcess = NULL;
}
if (Process == NULL && Address < (PVOID)KERNEL_BASE)
{
@ -652,11 +661,12 @@ MmCreateVirtualMapping(PEPROCESS Process,
ULONG flProtect,
ULONG PhysicalAddress)
{
if (!MmIsUsablePage((PVOID)PhysicalAddress))
if (!MmIsUsablePage((PVOID)PhysicalAddress))
{
DPRINT1("Page not usable\n");
DPRINT1("Page at address %x not usable\n", PhysicalAddress);
KeBugCheck(0);
}
return(MmCreateVirtualMappingUnsafe(Process,
Address,
flProtect,
@ -692,9 +702,11 @@ MmSetPageProtect(PEPROCESS Process, PVOID Address, ULONG flProtect)
ULONG Attributes = 0;
PULONG PageEntry;
PEPROCESS CurrentProcess = PsGetCurrentProcess();
Attributes = ProtectToPTE(flProtect);
DPRINT("MmSetPageProtect(Process %x Address %x flProtect %x)\n",
Process, Address, flProtect);
Attributes = ProtectToPTE(flProtect);
if (Process != CurrentProcess)
{
KeAttachProcess(Process);

View file

@ -1,4 +1,4 @@
/* $Id: mminit.c,v 1.17 2001/03/28 14:24:05 dwelch Exp $
/* $Id: mminit.c,v 1.18 2001/04/13 16:12:26 chorns Exp $
*
* COPYRIGHT: See COPYING in the top directory
* PROJECT: ReactOS kernel
@ -12,6 +12,7 @@
/* INCLUDES *****************************************************************/
#include <ddk/ntddk.h>
#include <internal/config.h>
#include <internal/i386/segment.h>
#include <internal/mm.h>
#include <internal/ntoskrnl.h>
@ -31,7 +32,7 @@
#define EXTENDED_MEMORY_SIZE (3*1024*1024)
/*
* Compiler defined symbol s
* Compiler defined symbols
*/
extern unsigned int _text_start__;
extern unsigned int _text_end__;
@ -79,7 +80,7 @@ VOID MmInitVirtualMemory(ULONG LastKernelAddress,
ULONG ParamLength = KernelLength;
NTSTATUS Status;
DPRINT("MmInitVirtualMemory(%x)\n",bp);
DPRINT("MmInitVirtualMemory(%x, %x)\n",LastKernelAddress, KernelLength);
LastKernelAddress = PAGE_ROUND_UP(LastKernelAddress);
@ -87,7 +88,7 @@ VOID MmInitVirtualMemory(ULONG LastKernelAddress,
// ExInitNonPagedPool(KERNEL_BASE + PAGE_ROUND_UP(kernel_len) + PAGESIZE);
ExInitNonPagedPool(LastKernelAddress + PAGESIZE);
/*
* Setup the system area descriptor list
*/
@ -102,7 +103,6 @@ VOID MmInitVirtualMemory(ULONG LastKernelAddress,
0,
&kernel_text_desc,
FALSE);
Length = PAGE_ROUND_UP(((ULONG)&_bss_end__)) -
PAGE_ROUND_UP(((ULONG)&_text_end__));
ParamLength = ParamLength - Length;
@ -151,6 +151,7 @@ VOID MmInitVirtualMemory(ULONG LastKernelAddress,
0,
&kernel_shared_data_desc,
FALSE);
MmSharedDataPagePhysicalAddress = MmAllocPage(0);
Status = MmCreateVirtualMapping(NULL,
(PVOID)KERNEL_SHARED_DATA_BASE,
@ -176,10 +177,14 @@ VOID MmInit1(ULONG FirstKrnlPhysAddr,
{
ULONG i;
ULONG kernel_len;
#ifndef MP
extern unsigned int unmap_me, unmap_me2, unmap_me3;
DPRINT("MmInit1(bp %x, LastKernelAddress %x)\n", bp,
LastKernelAddress);
#endif
DPRINT("MmInit1(FirstKrnlPhysAddr, %x, LastKrnlPhysAddr %x, LastKernelAddress %x)\n",
FirstKrnlPhysAddr,
LastKrnlPhysAddr,
LastKernelAddress);
/*
* FIXME: Set this based on the system command line
@ -205,12 +210,14 @@ VOID MmInit1(ULONG FirstKrnlPhysAddr,
* Initialize the kernel address space
*/
MmInitializeKernelAddressSpace();
/*
* Unmap low memory
*/
#ifndef MP
/* FIXME: This is broken in SMP mode */
MmDeletePageTable(NULL, 0);
#endif
/*
* Free all pages not used for kernel memory
* (we assume the kernel occupies a continuous range of physical
@ -247,30 +254,31 @@ VOID MmInit1(ULONG FirstKrnlPhysAddr,
* segment
*/
CHECKPOINT;
DPRINT("stext %x etext %x\n",(int)&stext,(int)&etext);
DPRINT("_text_start__ %x _text_end__ %x\n",(int)&_text_start__,(int)&_text_end__);
for (i=PAGE_ROUND_UP(((int)&_text_start__));
i<PAGE_ROUND_DOWN(((int)&_text_end__));i=i+PAGESIZE)
{
MmSetPageProtect(NULL,
(PVOID)i,
PAGE_EXECUTE_READ);
}
}
DPRINT("Invalidating between %x and %x\n",
LastKernelAddress,
KERNEL_BASE + PAGE_TABLE_SIZE);
for (i=(LastKernelAddress);
i<(KERNEL_BASE + PAGE_TABLE_SIZE);
i=i+PAGESIZE)
i<(KERNEL_BASE + PAGE_TABLE_SIZE);
i=i+PAGESIZE)
{
MmDeleteVirtualMapping(NULL, (PVOID)(i), FALSE, NULL, NULL);
MmDeleteVirtualMapping(NULL, (PVOID)(i), FALSE, NULL, NULL);
}
DPRINT("Almost done MmInit()\n");
#ifndef MP
/* FIXME: This is broken in SMP mode */
MmDeleteVirtualMapping(NULL, (PVOID)&unmap_me, FALSE, NULL, NULL);
MmDeleteVirtualMapping(NULL, (PVOID)&unmap_me2, FALSE, NULL, NULL);
MmDeleteVirtualMapping(NULL, (PVOID)&unmap_me3, FALSE, NULL, NULL);
#endif
/*
* Intialize memory areas
*/

View file

@ -1,4 +1,4 @@
/* $Id: psmgr.c,v 1.7 2000/06/03 21:36:32 ekohl Exp $
/* $Id: psmgr.c,v 1.8 2001/04/13 16:12:26 chorns Exp $
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
@ -10,6 +10,7 @@
/* INCLUDES **************************************************************/
#include <ddk/ntddk.h>
#include <internal/ke.h>
#include <internal/ps.h>
#include <reactos/version.h>
@ -26,10 +27,32 @@ VOID PiShutdownProcessManager(VOID)
VOID PiInitProcessManager(VOID)
{
#ifndef MP
HANDLE Phase1InitializationHandle;
NTSTATUS Status;
#endif
PsInitProcessManagment();
PsInitThreadManagment();
PsInitIdleThread();
PiInitApcManagement();
#ifndef MP
/* Create thread for Phase1Initialization */
Status = PsCreateSystemThread(
&Phase1InitializationHandle, /* Thread handle */
0, /* Desired access */
NULL, /* Object attributes */
NULL, /* Process handle */
NULL, /* Client id */
(PKSTART_ROUTINE)Phase1Initialization, /* Start routine */
NULL); /* Start context */
if (!NT_SUCCESS(Status)) {
DPRINT1("Could not create system thread (Status 0x%X)\n", Status);
KeBugCheck(0);
}
ZwClose(Phase1InitializationHandle);
#endif
}