Author: tkreuzer Date: Tue Sep 6 21:01:49 2011 New Revision: 53611
URL: http://svn.reactos.org/svn/reactos?rev=53611&view=rev Log: [HAL] Start implementing APIC support, which is needed for both SMP and x64. It will use the local APIC + I/O APIC for interrupt control, the RTC instead of the PIT for the timer interrupt (PIT doesn't always work with I/O APIC), the APIC timer for profiling and finally the TSC for the performance counter and KeStallExecutionProcessor. The code is incomplete and doesn't work yet
Added: trunk/reactos/hal/halx86/apic/ (with props) trunk/reactos/hal/halx86/apic/apic.c (with props) trunk/reactos/hal/halx86/apic/apic.h (with props) trunk/reactos/hal/halx86/apic/apictimer.c (with props) trunk/reactos/hal/halx86/apic/apictrap.S (with props) trunk/reactos/hal/halx86/apic/rtctimer.c (with props) trunk/reactos/hal/halx86/apic/tsc.c (with props) trunk/reactos/hal/halx86/apic/tsc.h (with props) trunk/reactos/hal/halx86/apic/tsccal.S (with props)
Propchange: trunk/reactos/hal/halx86/apic/ ------------------------------------------------------------------------------ --- bugtraq:logregex (added) +++ bugtraq:logregex Tue Sep 6 21:01:49 2011 @@ -1,0 +1,2 @@ +([Ii]ssue|[Bb]ug)s? #?(\d+)(,? ?#?(\d+))*(,? ?(and |or )?#?(\d+))? +(\d+)
Propchange: trunk/reactos/hal/halx86/apic/ ------------------------------------------------------------------------------ bugtraq:message = See issue #%BUGID% for more details.
Propchange: trunk/reactos/hal/halx86/apic/ ------------------------------------------------------------------------------ bugtraq:url = http://www.reactos.org/bugzilla/show_bug.cgi?id=%BUGID%
Propchange: trunk/reactos/hal/halx86/apic/ ------------------------------------------------------------------------------ tsvn:logminsize = 10
Added: trunk/reactos/hal/halx86/apic/apic.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/hal/halx86/apic/apic.c?rev=... ============================================================================== --- trunk/reactos/hal/halx86/apic/apic.c (added) +++ trunk/reactos/hal/halx86/apic/apic.c [iso-8859-1] Tue Sep 6 21:01:49 2011 @@ -1,0 +1,693 @@ +/* + * PROJECT: ReactOS HAL + * LICENSE: GNU GPL - See COPYING in the top level directory + * FILE: hal/halx86/generic/apic.c + * PURPOSE: HAL APIC Management and Control Code + * PROGRAMMERS: Timo Kreuzer (timo.kreuzer@reactos.org) + * REFERENCES: http://www.joseflores.com/docs/ExploringIrql.html + * http://www.codeproject.com/KB/system/soviet_kernel_hack.aspx + * http://bbs.unixmap.net/thread-2022-1-1.html + */ + +/* INCLUDES *******************************************************************/ + +#include <hal.h> +#define NDEBUG +#include <debug.h> + +#include "apic.h" + +/* GLOBALS ********************************************************************/ + +UCHAR HalpVectorToIndex[256]; + +#ifndef _M_AMD64 +static const UCHAR +HalpIRQLtoTPR[32] = +{ + 0x00, /* 0 PASSIVE_LEVEL */ + 0x3d, /* 1 APC_LEVEL */ + 0x41, /* 2 DISPATCH_LEVEL */ + 0x41, /* 3 \ */ + 0x51, /* 4 \ */ + 0x61, /* 5 | */ + 0x71, /* 6 | */ + 0x81, /* 7 | */ + 0x91, /* 8 | */ + 0xa1, /* 9 | */ + 0xb1, /* 10 | */ + 0xb1, /* 11 | */ + 0xb1, /* 12 | */ + 0xb1, /* 13 | */ + 0xb1, /* 14 | */ + 0xb1, /* 15 DEVICE IRQL */ + 0xb1, /* 16 | */ + 0xb1, /* 17 | */ + 0xb1, /* 18 | */ + 0xb1, /* 19 | */ + 0xb1, /* 20 | */ + 0xb1, /* 21 | */ + 0xb1, /* 22 | */ + 0xb1, /* 23 | */ + 0xb1, /* 24 | */ + 0xb1, /* 25 / */ + 0xb1, /* 26 / */ + 0xc1, /* 27 PROFILE_LEVEL */ + 0xd1, /* 28 CLOCK2_LEVEL */ + 0xe1, /* 29 IPI_LEVEL */ + 0xef, /* 30 POWER_LEVEL */ + 0xff, /* 31 HIGH_LEVEL */ +}; + +static const KIRQL +HalVectorToIRQL[16] = +{ + 0, /* 00 PASSIVE_LEVEL */ + 0xff, /* 10 */ + 0xff, /* 20 */ + 1, /* 3D APC_LEVEL */ + 2, /* 41 DISPATCH_LEVEL */ + 4, /* 50 \ */ + 5, /* 60 \ */ + 6, /* 70 | */ + 7, /* 80 DEVICE IRQL */ + 8, /* 90 | */ + 9, /* A0 / */ + 10, /* B0 / */ + 27, /* C1 PROFILE_LEVEL */ + 28, /* D1 CLOCK2_LEVEL */ + 29, /* E1 IPI_LEVEL / EF POWER_LEVEL */ + 31, /* FF HIGH_LEVEL */ +}; +#endif + +/* PRIVATE FUNCTIONS **********************************************************/ + +ULONG +FORCEINLINE +IOApicRead(UCHAR Register) +{ + /* Select the register, then do the read */ + *(volatile ULONG *)(IOAPIC_BASE + IOAPIC_IOREGSEL) = Register; + return *(volatile ULONG *)(IOAPIC_BASE + IOAPIC_IOWIN); +} + +VOID +FORCEINLINE +IOApicWrite(UCHAR Register, ULONG Value) +{ + /* Select the register, then do the write */ + *(volatile ULONG *)(IOAPIC_BASE + IOAPIC_IOREGSEL) = Register; + *(volatile ULONG *)(IOAPIC_BASE + IOAPIC_IOWIN) = Value; +} + +KIRQL +FORCEINLINE +ApicGetProcessorIrql(VOID) +{ + /* Read the TPR and convert it to an IRQL */ + return TprToIrql(ApicRead(APIC_PPR)); +} + +KIRQL +FORCEINLINE +ApicGetCurrentIrql(VOID) +{ + /* Read the TPR and convert it to an IRQL */ + return TprToIrql(ApicRead(APIC_TPR)); +} + +VOID +FORCEINLINE +ApicSetCurrentIrql(KIRQL Irql) +{ + /* Convert IRQL and write the TPR */ + ApicWrite(APIC_TPR, IrqlToTpr(Irql)); +} + +UCHAR +FASTCALL +HalpIrqToVector(UCHAR Irq) +{ + IOAPIC_REDIRECTION_REGISTER ReDirReg; + + /* Read low dword of the redirection entry */ + ReDirReg.Long0 = IOApicRead(IOAPIC_REDTBL + 2 * Irq); + + /* Return the vector */ + return (UCHAR)ReDirReg.Vector; +} + +KIRQL +FASTCALL +HalpVectorToIrql(UCHAR Vector) +{ + return TprToIrql(Vector >> 2); +} + +UCHAR +FASTCALL +HalpVectorToIrq(UCHAR Vector) +{ + return HalpVectorToIndex[Vector]; +} + +VOID +NTAPI +HalpInitializeLegacyPIC(VOID) +{ + I8259_ICW1 Icw1; + I8259_ICW2 Icw2; + I8259_ICW3 Icw3; + I8259_ICW4 Icw4; + + /* Initialize ICW1 for master, interval 8, edge-triggered mode with ICW4 */ + Icw1.NeedIcw4 = TRUE; + Icw1.OperatingMode = Cascade; + Icw1.Interval = Interval8; + Icw1.InterruptMode = EdgeTriggered; + Icw1.Init = TRUE; + Icw1.InterruptVectorAddress = 0; + __outbyte(PIC1_CONTROL_PORT, Icw1.Bits); + + /* ICW2 - interrupt vector offset */ + Icw2.Bits = PRIMARY_VECTOR_BASE; + __outbyte(PIC1_DATA_PORT, Icw2.Bits); + + /* Connect slave to IRQ 2 */ + Icw3.Bits = 0; + Icw3.SlaveIrq2 = TRUE; + __outbyte(PIC1_DATA_PORT, Icw3.Bits); + + /* Enable 8086 mode, non-automatic EOI, non-buffered mode, non special fully nested mode */ + Icw4.SystemMode = New8086Mode; + Icw4.EoiMode = NormalEoi; + Icw4.BufferedMode = NonBuffered; + Icw4.SpecialFullyNestedMode = FALSE; + Icw4.Reserved = 0; + __outbyte(PIC1_DATA_PORT, Icw4.Bits); + + /* Mask all interrupts */ + __outbyte(PIC1_DATA_PORT, 0xFF); + + /* Initialize ICW1 for slave, interval 8, edge-triggered mode with ICW4 */ + Icw1.NeedIcw4 = TRUE; + Icw1.InterruptMode = EdgeTriggered; + Icw1.OperatingMode = Cascade; + Icw1.Interval = Interval8; + Icw1.Init = TRUE; + Icw1.InterruptVectorAddress = 0; /* This is only used in MCS80/85 mode */ + __outbyte(PIC2_CONTROL_PORT, Icw1.Bits); + + /* Set interrupt vector base */ + Icw2.Bits = PRIMARY_VECTOR_BASE + 8; + __outbyte(PIC2_DATA_PORT, Icw2.Bits); + + /* Slave ID */ + Icw3.Bits = 0; + Icw3.SlaveId = 2; + __outbyte(PIC2_DATA_PORT, Icw3.Bits); + + /* Enable 8086 mode, non-automatic EOI, non-buffered mode, non special fully nested mode */ + Icw4.SystemMode = New8086Mode; + Icw4.EoiMode = NormalEoi; + Icw4.BufferedMode = NonBuffered; + Icw4.SpecialFullyNestedMode = FALSE; + Icw4.Reserved = 0; + __outbyte(PIC2_DATA_PORT, Icw4.Bits); + + /* Mask all interrupts */ + __outbyte(PIC2_DATA_PORT, 0xFF); +} + + +VOID +ApicInitializeLocalApic(ULONG Cpu) +{ + APIC_BASE_ADRESS_REGISTER BaseRegister; + APIC_SPURIOUS_INERRUPT_REGISTER SpIntRegister; + LVT_REGISTER LvtEntry; + + /* Enable the APIC if it wasn't yet */ + BaseRegister.Long = __readmsr(MSR_APIC_BASE); + BaseRegister.Enable = 1; + BaseRegister.BootStrapCPUCore = (Cpu == 0); + __writemsr(MSR_APIC_BASE, BaseRegister.Long); + + DPRINT1("ApicBase for Cpu %u PhysicalAddress = %p\n", Cpu, BaseRegister.BaseAddress); + DPRINT1("ApicVersion = 0x%lx\n", ApicRead(0x30)); + + /* Set spurious vector and SoftwareEnable to 1 */ + SpIntRegister.Long = ApicRead(APIC_SIVR); + SpIntRegister.Vector = APIC_SPURIOUS_VECTOR; + SpIntRegister.SoftwareEnable = 1; + SpIntRegister.FocusCPUCoreChecking = 0; + ApicWrite(APIC_SIVR, SpIntRegister.Long); + + /* Set the spurious ISR */ + KeRegisterInterruptHandler(APIC_SPURIOUS_VECTOR, ApicSpuriousService); + + /* Create a template LVT */ + LvtEntry.Long = 0; + LvtEntry.Vector = 0xFF; + LvtEntry.MessageType = APIC_MT_Fixed; + LvtEntry.DeliveryStatus = 0; + LvtEntry.RemoteIRR = 0; + LvtEntry.TriggerMode = APIC_TGM_Edge; + LvtEntry.Mask = 1; + LvtEntry.TimerMode = 0; + + /* Initalize and mask LVTs */ + ApicWrite(APIC_TMRLVTR, LvtEntry.Long); + ApicWrite(APIC_THRMLVTR, LvtEntry.Long); + ApicWrite(APIC_PCLVTR, LvtEntry.Long); + ApicWrite(APIC_EXT0LVTR, LvtEntry.Long); + ApicWrite(APIC_EXT1LVTR, LvtEntry.Long); + ApicWrite(APIC_EXT2LVTR, LvtEntry.Long); + ApicWrite(APIC_EXT3LVTR, LvtEntry.Long); + + /* LINT0 */ + LvtEntry.Vector = APIC_SPURIOUS_VECTOR; + LvtEntry.MessageType = APIC_MT_ExtInt; + ApicWrite(APIC_LINT0, LvtEntry.Long); + + /* Enable LINT1 (NMI) */ + LvtEntry.Mask = 0; + LvtEntry.Vector = APIC_NMI_VECTOR; + LvtEntry.MessageType = APIC_MT_NMI; + LvtEntry.TriggerMode = APIC_TGM_Level; + ApicWrite(APIC_LINT1, LvtEntry.Long); + + /* Enable error LVTR */ + LvtEntry.Vector = APIC_ERROR_VECTOR; + LvtEntry.MessageType = APIC_MT_Fixed; + ApicWrite(APIC_ERRLVTR, LvtEntry.Long); + + DPRINT1("Error code = 0x%lx\n", ApicRead(0x280)); +} + +VOID +NTAPI +ApicInitializeProcessor( + IN ULONG ProcessorNumber, + IN PLOADER_PARAMETER_BLOCK LoaderBlock) +{ + DPRINT1("ApicInitializeProcessor(%ld)\n", ProcessorNumber); + + /* Initialize the local APIC for this cpu */ + ApicInitializeLocalApic(ProcessorNumber); + + /* Initialize the timer */ + ApicInitializeTimer(ProcessorNumber); + +} + +VOID +FORCEINLINE +ApicWriteIORedirectionEntry( + UCHAR Index, + IOAPIC_REDIRECTION_REGISTER ReDirReg) +{ + IOApicWrite(IOAPIC_REDTBL + 2 * Index, ReDirReg.Long0); + IOApicWrite(IOAPIC_REDTBL + 2 * Index + 1, ReDirReg.Long1); +} + +IOAPIC_REDIRECTION_REGISTER +FORCEINLINE +ApicReadIORedirectionEntry( + UCHAR Index) +{ + IOAPIC_REDIRECTION_REGISTER ReDirReg; + + ReDirReg.Long0 = IOApicRead(IOAPIC_REDTBL + 2 * Index); + ReDirReg.Long1 = IOApicRead(IOAPIC_REDTBL + 2 * Index + 1); + + return ReDirReg; +} + +UCHAR +NTAPI +HalpAllocateSystemInterrupt( + IN UCHAR Irq, + IN KIRQL Irql) +{ + IOAPIC_REDIRECTION_REGISTER ReDirReg; + IN UCHAR Vector; + + /* Start with low vector */ + Vector = IrqlToTpr(Irql); + + /* Find an empty vector */ + while (HalpVectorToIndex[Vector] != 0xFF) + { + Vector++; + + /* Check if we went over the edge */ + if (TprToIrql(Vector) > Irql) + { + /* Nothing free, return failure */ + return 0; + } + } + + /* Save irq in the table */ + HalpVectorToIndex[Vector] = Irq; + + /* Setup a redirection entry */ + ReDirReg.Vector = Vector; + ReDirReg.DeliveryMode = APIC_MT_LowestPriority; + ReDirReg.DestinationMode = APIC_DM_Logical; + ReDirReg.DeliveryStatus = 0; + ReDirReg.Polarity = 0; + ReDirReg.RemoteIRR = 0; + ReDirReg.TriggerMode = APIC_TGM_Edge; + ReDirReg.Mask = 1; + ReDirReg.Reserved = 0; + ReDirReg.Destination = 0; + + /* Initialize entry */ + IOApicWrite(IOAPIC_REDTBL + 2 * Irq, ReDirReg.Long0); + IOApicWrite(IOAPIC_REDTBL + 2 * Irq + 1, ReDirReg.Long1); + + return Vector; +} + +VOID +NTAPI +ApicInitializeIOApic(VOID) +{ + PHARDWARE_PTE Pte; + IOAPIC_REDIRECTION_REGISTER ReDirReg; + UCHAR Index; + ULONG Vector; + + /* Map the I/O Apic page */ + Pte = HalAddressToPte(IOAPIC_BASE); + Pte->PageFrameNumber = IOAPIC_PHYS_BASE / PAGE_SIZE; + Pte->Valid = 1; + Pte->Write = 1; + Pte->Owner = 1; + Pte->CacheDisable = 1; + Pte->Global = 1; + _ReadWriteBarrier(); + + /* Setup a redirection entry */ + ReDirReg.Vector = 0xFF; + ReDirReg.DeliveryMode = APIC_MT_Fixed; + ReDirReg.DestinationMode = APIC_DM_Physical; + ReDirReg.DeliveryStatus = 0; + ReDirReg.Polarity = 0; + ReDirReg.RemoteIRR = 0; + ReDirReg.TriggerMode = APIC_TGM_Edge; + ReDirReg.Mask = 1; + ReDirReg.Reserved = 0; + ReDirReg.Destination = 0; + + /* Loop all table entries */ + for (Index = 0; Index < 24; Index++) + { + /* Initialize entry */ + IOApicWrite(IOAPIC_REDTBL + 2 * Index, ReDirReg.Long0); + IOApicWrite(IOAPIC_REDTBL + 2 * Index + 1, ReDirReg.Long1); + } + + /* Init the vactor to index table */ + for (Vector = 0; Vector <= 255; Vector++) + { + HalpVectorToIndex[Vector] = 0xFF; + } + + // HACK: Allocate all IRQs, should rather do that on demand + for (Index = 0; Index <= 15; Index++) + { + /* Map the IRQs to IRQLs like with the PIC */ + HalpAllocateSystemInterrupt(Index, 27 - Index); + } + + /* Enable the timer interrupt */ + ReDirReg.Vector = APIC_CLOCK_VECTOR; + ReDirReg.DestinationMode = APIC_DM_Logical; + ReDirReg.TriggerMode = APIC_TGM_Edge; + ReDirReg.Mask = 0; + IOApicWrite(IOAPIC_REDTBL + 2 * APIC_CLOCK_INDEX, ReDirReg.Long0); + +} + +VOID +NTAPI +HalpInitializePICs(IN BOOLEAN EnableInterrupts) +{ + ULONG_PTR EFlags; + + /* Save EFlags and disable interrupts */ + EFlags = __readeflags(); + _disable(); + + /* Initialize the local APIC for this cpu */ + ApicInitializeLocalApic(0); + + /* Initialize and mask the PIC */ + HalpInitializeLegacyPIC(); + + /* Initialize the I/O APIC */ + ApicInitializeIOApic(); + ApicWrite(APIC_EOI, 0); + + /* Register interrupt handlers */ + KeRegisterInterruptHandler(APIC_CLOCK_VECTOR, HalpClockInterrupt); + KeRegisterInterruptHandler(APC_VECTOR, HalpApcInterrupt); + KeRegisterInterruptHandler(DPC_VECTOR, HalpDispatchInterrupt); + + // HACK, since we messed with the value, should init the local apic in + // HalInitializeProcessor instead + ApicSetCurrentIrql(APC_LEVEL); + ASSERT(ApicGetProcessorIrql() <= APC_LEVEL); + +__debugbreak(); + +HalpInitializeClock(); +//HalpCalibrateStallExecution(); +_enable(); +for (;;); + + + /* Restore interrupt state */ + if (EnableInterrupts) EFlags |= EFLAGS_INTERRUPT_MASK; + __writeeflags(EFlags); +} + +VOID +DECLSPEC_NORETURN +FASTCALL +HalpApcInterruptHandler(IN PKTRAP_FRAME TrapFrame) +{ + ASSERT(ApicGetCurrentIrql() < APC_LEVEL); + ASSERT(ApicGetProcessorIrql() == APC_LEVEL); + + UNIMPLEMENTED; + ASSERT(FALSE); +} + +VOID +DECLSPEC_NORETURN +FASTCALL +HalpDispatchInterruptHandler(IN PKTRAP_FRAME TrapFrame) +{ + KIRQL OldIrql = ApicGetCurrentIrql(); +__debugbreak(); + ASSERT(OldIrql < DISPATCH_LEVEL); + ASSERT(ApicGetProcessorIrql() == DISPATCH_LEVEL); + + ApicSetCurrentIrql(DISPATCH_LEVEL); + + /* Enable interrupts and call the kernel's DPC interrupt handler */ + _enable(); + KiDispatchInterrupt(); + _disable(); + + ApicSetCurrentIrql(OldIrql); + + ApicWrite(APIC_EOI, 0); + + /* Exit the interrupt */ + KiEoiHelper(TrapFrame); +} + + +/* PUBLIC FUNCTIONS ***********************************************************/ + +VOID +FASTCALL +HalRequestSoftwareInterrupt(IN KIRQL Irql) +{ + APIC_COMMAND_REGISTER CommandRegister; + + /* Setup the command register */ + CommandRegister.Long0 = 0; + CommandRegister.Vector = IrqlToTpr(Irql); + CommandRegister.MessageType = APIC_MT_Fixed; + CommandRegister.TriggerMode = APIC_TGM_Edge; + CommandRegister.DestinationShortHand = APIC_DSH_Self; + + /* Write the low dword to send the interrupt */ + ApicWrite(APIC_ICR0, CommandRegister.Long0); +} + +VOID +FASTCALL +HalClearSoftwareInterrupt( + IN KIRQL Irql) +{ + /* Nothing to do */ +} + +BOOLEAN +NTAPI +HalEnableSystemInterrupt( + IN UCHAR Vector, + IN KIRQL Irql, + IN KINTERRUPT_MODE InterruptMode) +{ + IOAPIC_REDIRECTION_REGISTER ReDirReg; + UCHAR Index; + ASSERT(Irql <= HIGH_LEVEL); + ASSERT((IrqlToTpr(Irql) & 0xF0) == (Vector & 0xF0)); + + Index = HalpVectorToIndex[Vector]; + + /* Read lower dword of redirection entry */ + ReDirReg.Long0 = IOApicRead(IOAPIC_REDTBL + 2 * Index); + + ReDirReg.Vector = Vector; + ReDirReg.DeliveryMode = APIC_MT_LowestPriority; + ReDirReg.DestinationMode = APIC_DM_Logical; + ReDirReg.TriggerMode = 1 - InterruptMode; + ReDirReg.Mask = FALSE; + + /* Write back lower dword */ + IOApicWrite(IOAPIC_REDTBL + 2 * Irql, ReDirReg.Long0); + + return TRUE; +} + +VOID +NTAPI +HalDisableSystemInterrupt( + IN UCHAR Vector, + IN KIRQL Irql) +{ + IOAPIC_REDIRECTION_REGISTER ReDirReg; + UCHAR Index; + ASSERT(Irql <= HIGH_LEVEL); + + Index = HalpVectorToIndex[Vector]; + + /* Read lower dword of redirection entry */ + ReDirReg.Long0 = IOApicRead(IOAPIC_REDTBL + 2 * Index); + + /* Mask it */ + ReDirReg.Mask = 1; + + /* Write back lower dword */ + IOApicWrite(IOAPIC_REDTBL + 2 * Irql, ReDirReg.Long0); +} + +BOOLEAN +NTAPI +HalBeginSystemInterrupt( + IN KIRQL Irql, + IN UCHAR Vector, + OUT PKIRQL OldIrql) +{ + /* Get the current IRQL */ + *OldIrql = ApicGetCurrentIrql(); + + /* Set the new IRQL */ + ApicSetCurrentIrql(Irql); + + /* Turn on interrupts */ + _enable(); + + /* Success */ + return TRUE; +} + +VOID +NTAPI +HalEndSystemInterrupt( + IN KIRQL OldIrql, + IN PKTRAP_FRAME TrapFrame) +{ + /* Restore the old IRQL */ + ApicSetCurrentIrql(OldIrql); + + /* Write 0 to the EndOfInterruptRegister for level triggered ints */ + ApicWrite(APIC_EOI, 0); +} + +#ifndef _M_AMD64 + +KIRQL +NTAPI +KeGetCurrentIrql(VOID) +{ + /* Read the current TPR and convert it to an IRQL */ + return ApicGetCurrentIrql(); +} + +VOID +FASTCALL +KfLowerIrql( + IN KIRQL OldIrql) +{ +#if DBG + /* Validate correct lower */ + if (OldIrql > ApicGetCurrentIrql()) + { + /* Crash system */ + KeBugCheck(IRQL_NOT_LESS_OR_EQUAL); + } +#endif + /* Convert the new IRQL to a TPR value and write the register */ + ApicSetCurrentIrql(OldIrql); +} + +KIRQL +FASTCALL +KfRaiseIrql( + IN KIRQL NewIrql) +{ + KIRQL OldIrql; + + /* Read the current TPR and convert it to an IRQL */ + OldIrql = ApicGetCurrentIrql(); +#if DBG + /* Validate correct raise */ + if (OldIrql > NewIrql) + { + /* Crash system */ + KeBugCheck(IRQL_NOT_GREATER_OR_EQUAL); + } +#endif + /* Convert the new IRQL to a TPR value and write the register */ + ApicSetCurrentIrql(NewIrql); + + return OldIrql; +} + +KIRQL +NTAPI +KeRaiseIrqlToDpcLevel(VOID) +{ + return KfRaiseIrql(DISPATCH_LEVEL); +} + +KIRQL +NTAPI +KeRaiseIrqlToSynchLevel(VOID) +{ + return KfRaiseIrql(SYNCH_LEVEL); +} + +#endif /* !_M_AMD64 */ +
Propchange: trunk/reactos/hal/halx86/apic/apic.c ------------------------------------------------------------------------------ svn:eol-style = native
Added: trunk/reactos/hal/halx86/apic/apic.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/hal/halx86/apic/apic.h?rev=... ============================================================================== --- trunk/reactos/hal/halx86/apic/apic.h (added) +++ trunk/reactos/hal/halx86/apic/apic.h [iso-8859-1] Tue Sep 6 21:01:49 2011 @@ -1,0 +1,271 @@ + +#ifdef _M_AMD64 +#define APIC_BASE 0xfffffffffee00000ULL; +#define ZERO_VECTOR 0x00 // IRQL 00 +#define APC_VECTOR 0x3D // IRQL 01 +#define APIC_SPURIOUS_VECTOR 0x3f +#define DPC_VECTOR 0x41 // IRQL 02 +#define APIC_GENERIC_VECTOR 0xC1 // IRQL 27 +#define APIC_CLOCK_VECTOR 0xD1 // IRQL 28 +#define APIC_SYNCH_VECTOR 0xD1 // IRQL 28 +#define APIC_IPI_VECTOR 0xE1 // IRQL 29 +#define APIC_ERROR_VECTOR 0xE3 +#define POWERFAIL_VECTOR 0xEF // IRQL 30 +#define APIC_PROFILE_VECTOR 0xFD // IRQL 31 +#define APIC_NMI_VECTOR 0xFF +#define IrqlToTpr(Irql) (Irql << 4) +#define TprToIrql(Tpr) (Tpr >> 4) +#else +#define APIC_BASE 0xFFFE0000 +#define IOAPIC_BASE 0xFFFE1000 // checkme +#define IOAPIC_PHYS_BASE 0xFEC00000 +#define ZERO_VECTOR 0x00 // IRQL 00 +#define APIC_SPURIOUS_VECTOR 0x1f +#define APC_VECTOR 0x3D // IRQL 01 +#define DPC_VECTOR 0x41 // IRQL 02 +#define APIC_GENERIC_VECTOR 0xC1 // IRQL 27 +#define APIC_CLOCK_VECTOR 0xD1 // IRQL 28 +#define APIC_SYNCH_VECTOR 0xD1 // IRQL 28 +#define APIC_IPI_VECTOR 0xE1 // IRQL 29 +#define APIC_ERROR_VECTOR 0xE3 +#define POWERFAIL_VECTOR 0xEF // IRQL 30 +#define APIC_PROFILE_VECTOR 0xFD // IRQL 31 +#define APIC_NMI_VECTOR 0xFF +#define IrqlToTpr(Irql) (HalpIRQLtoTPR[Irql]) +#define TprToIrql(Tpr) (HalVectorToIRQL[Tpr >> 4]) +#endif + +#define MSR_APIC_BASE 0x0000001B +#define APIC_CLOCK_INDEX 8 + + +/* 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_RRR 0x00C0 /* Remote Read Register () */ +#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_TMRLVTR 0x0320 /* Timer Local Vector Table (R/W) */ +#define APIC_THRMLVTR 0x0330 /* Thermal Local Vector Table */ +#define APIC_PCLVTR 0x0340 /* Performance Counter Local Vector Table (R/W) */ +#define APIC_LINT0 0x0350 /* LINT0 Local Vector Table (R/W) */ +#define APIC_LINT1 0x0360 /* LINT1 Local Vector Table (R/W) */ +#define APIC_ERRLVTR 0x0370 /* Error Local Vector Table (R/W) */ +#define APIC_TICR 0x0380 /* Initial Count Register for Timer (R/W) */ +#define APIC_TCCR 0x0390 /* Current Count Register for Timer (R) */ +#define APIC_TDCR 0x03E0 /* Timer Divide Configuration Register (R/W) */ +#define APIC_EAFR 0x0400 /* extended APIC Feature register (R/W) */ +#define APIC_EACR 0x0410 /* Extended APIC Control Register (R/W) */ +#define APIC_SEOI 0x0420 /* Specific End Of Interrupt Register (W) */ +#define APIC_EXT0LVTR 0x0500 /* Extended Interrupt 0 Local Vector Table */ +#define APIC_EXT1LVTR 0x0510 /* Extended Interrupt 1 Local Vector Table */ +#define APIC_EXT2LVTR 0x0520 /* Extended Interrupt 2 Local Vector Table */ +#define APIC_EXT3LVTR 0x0530 /* Extended Interrupt 3 Local Vector Table */ + +enum +{ + APIC_MT_Fixed = 0, + APIC_MT_LowestPriority = 1, + APIC_MT_SMI = 2, + APIC_MT_RemoteRead = 3, + APIC_MT_NMI = 4, + APIC_MT_INIT = 5, + APIC_MT_Startup = 6, + APIC_MT_ExtInt = 7, +}; + +enum +{ + APIC_TGM_Edge, + APIC_TGM_Level +}; + +enum +{ + APIC_DM_Physical, + APIC_DM_Logical +}; + +enum +{ + APIC_DSH_Destination, + APIC_DSH_Self, + APIC_DSH_AllIncludingSelf, + APIC_DSH_AllExclusingSelf +}; + +enum +{ + TIMER_DV_DivideBy2 = 0, + TIMER_DV_DivideBy4 = 1, + TIMER_DV_DivideBy8 = 2, + TIMER_DV_DivideBy16 = 3, + TIMER_DV_DivideBy32 = 8, + TIMER_DV_DivideBy64 = 9, + TIMER_DV_DivideBy128 = 10, + TIMER_DV_DivideBy1 = 11, +}; + + +typedef union _APIC_BASE_ADRESS_REGISTER +{ + ULONG64 Long; + struct + { + ULONG64 Reserved1:8; + ULONG64 BootStrapCPUCore:1; + ULONG64 Reserved2:2; + ULONG64 Enable:1; + ULONG64 BaseAddress:40; + ULONG64 ReservedMBZ:12; + }; +} APIC_BASE_ADRESS_REGISTER; + +typedef union _APIC_SPURIOUS_INERRUPT_REGISTER +{ + ULONG Long; + struct + { + ULONG Vector:8; + ULONG SoftwareEnable:1; + ULONG FocusCPUCoreChecking:1; + ULONG ReservedMBZ:22; + }; +} APIC_SPURIOUS_INERRUPT_REGISTER; + +typedef union +{ + ULONG Long; + struct + { + ULONG Version:8; + ULONG ReservedMBZ:8; + ULONG MaxLVT:8; + ULONG ReservedMBZ1:7; + ULONG ExtRegSpacePresent:1; + }; +} APIC_VERSION_REGISTER; + +typedef union +{ + ULONG Long; + struct + { + ULONG Version:1; + ULONG SEOIEnable:1; + ULONG ExtApicIdEnable:1; + ULONG ReservedMBZ:29; + }; +} APIC_EXTENDED_CONTROL_REGISTER; + +typedef union _APIC_COMMAND_REGISTER +{ + ULONGLONG LongLong; + struct + { + ULONG Long0; + ULONG Long1; + }; + struct + { + ULONGLONG Vector:8; + ULONGLONG MessageType:3; + ULONGLONG DestinationMode:1; + ULONGLONG DeliveryStatus:1; + ULONGLONG ReservedMBZ:1; + ULONGLONG Level:1; + ULONGLONG TriggerMode:1; + ULONGLONG RemoteReadStatus:2; + ULONGLONG DestinationShortHand:2; + ULONGLONG Reserved2MBZ:36; + ULONGLONG Destination:8; + }; +} APIC_COMMAND_REGISTER; + +typedef union +{ + ULONG Long; + struct + { + ULONG Vector:8; + ULONG MessageType:3; + ULONG ReservedMBZ:1; + ULONG DeliveryStatus:1; + ULONG Reserved1MBZ:1; + ULONG RemoteIRR:1; + ULONG TriggerMode:1; + ULONG Mask:1; + ULONG TimerMode:1; + ULONG Reserved2MBZ:13; + }; +} LVT_REGISTER; + + +enum +{ + IOAPIC_IOREGSEL = 0x00, + IOAPIC_IOWIN = 0x10 +}; + +enum +{ + IOAPIC_ID = 0x00, + IOAPIC_VER = 0x01, + IOAPIC_ARB = 0x02, + IOAPIC_REDTBL = 0x28 +}; + +typedef union _IOAPIC_REDIRECTION_REGISTER +{ + ULONGLONG LongLong; + struct + { + ULONG Long0; + ULONG Long1; + }; + struct + { + ULONGLONG Vector:8; + ULONGLONG DeliveryMode:3; + ULONGLONG DestinationMode:1; + ULONGLONG DeliveryStatus:1; + ULONGLONG Polarity:1; + ULONGLONG RemoteIRR:1; + ULONGLONG TriggerMode:1; + ULONGLONG Mask:1; + ULONGLONG Reserved:39; + ULONGLONG Destination:8; + }; +} IOAPIC_REDIRECTION_REGISTER; + +ULONG +FORCEINLINE +ApicRead(ULONG Offset) +{ + return *(volatile ULONG *)(APIC_BASE + Offset); +} + +VOID +FORCEINLINE +ApicWrite(ULONG Offset, ULONG Value) +{ + *(volatile ULONG *)(APIC_BASE + Offset) = Value; +} + +VOID +NTAPI +ApicInitializeTimer(ULONG Cpu); + +VOID ApicSpuriousService(VOID); +
Propchange: trunk/reactos/hal/halx86/apic/apic.h ------------------------------------------------------------------------------ svn:eol-style = native
Added: trunk/reactos/hal/halx86/apic/apictimer.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/hal/halx86/apic/apictimer.c... ============================================================================== --- trunk/reactos/hal/halx86/apic/apictimer.c (added) +++ trunk/reactos/hal/halx86/apic/apictimer.c [iso-8859-1] Tue Sep 6 21:01:49 2011 @@ -1,0 +1,84 @@ +/* + * PROJECT: ReactOS HAL + * LICENSE: GPL - See COPYING in the top level directory + * FILE: hal/halx86/apic/apictimer.c + * PURPOSE: System Profiling + * PROGRAMMERS: Timo Kreuzer (timo.kreuzer@reactos.org) + */ + +/* INCLUDES ******************************************************************/ + +#include <hal.h> +#define NDEBUG +#include <debug.h> + +#include "apic.h" + +extern LARGE_INTEGER HalpCpuClockFrequency; + +/* TIMER FUNCTIONS ************************************************************/ + +VOID +NTAPI +ApicSetTimerInterval(ULONG MicroSeconds) +{ + LVT_REGISTER LvtEntry; + ULONGLONG TimerInterval; + + /* Calculate the Timer interval */ + TimerInterval = HalpCpuClockFrequency.QuadPart * MicroSeconds / 1000000; + + /* Set the count interval */ + ApicWrite(APIC_TICR, (ULONG)TimerInterval); + + /* Set to periodic */ + LvtEntry.Long = 0; + LvtEntry.TimerMode = 1; + LvtEntry.Vector = APIC_PROFILE_VECTOR; + LvtEntry.Mask = 0; + ApicWrite(APIC_TMRLVTR, LvtEntry.Long); + +} + +VOID +NTAPI +ApicInitializeTimer(ULONG Cpu) +{ + + /* Initialize the TSC */ + //HalpInitializeTsc(); + + /* Set clock multiplier to 1 */ + ApicWrite(APIC_TDCR, TIMER_DV_DivideBy1); + + ApicSetTimerInterval(1000); + +// KeSetTimeIncrement +} + + +/* PUBLIC FUNCTIONS ***********************************************************/ + +VOID +NTAPI +HalStartProfileInterrupt(IN KPROFILE_SOURCE ProfileSource) +{ + UNIMPLEMENTED; + return; +} + +VOID +NTAPI +HalStopProfileInterrupt(IN KPROFILE_SOURCE ProfileSource) +{ + UNIMPLEMENTED; + return; +} + +ULONG_PTR +NTAPI +HalSetProfileInterval(IN ULONG_PTR Interval) +{ + UNIMPLEMENTED; + return Interval; +}
Propchange: trunk/reactos/hal/halx86/apic/apictimer.c ------------------------------------------------------------------------------ svn:eol-style = native
Added: trunk/reactos/hal/halx86/apic/apictrap.S URL: http://svn.reactos.org/svn/reactos/trunk/reactos/hal/halx86/apic/apictrap.S?... ============================================================================== --- trunk/reactos/hal/halx86/apic/apictrap.S (added) +++ trunk/reactos/hal/halx86/apic/apictrap.S [iso-8859-1] Tue Sep 6 21:01:49 2011 @@ -1,0 +1,36 @@ +/* + * FILE: hal/halx86/apic/apictrap.S + * COPYRIGHT: See COPYING in the top level directory + * PURPOSE: System Traps, Entrypoints and Exitpoints + * PROGRAMMER: Timo Kreuzer (timo.kreuzer@reactos.org) + * NOTE: See asmmacro.S for the shared entry/exit code. + */ + +/* INCLUDES ******************************************************************/ + +#include <asm.inc> +#include <internal/i386/asmmacro.S> + +#ifdef _M_AMD64 +#include <ksamd64.inc> +PUBLIC ApicSpuriousService +#else +#include <ks386.inc> +PUBLIC _ApicSpuriousService +#endif + +.code + +TRAP_ENTRY HalpTrap0D, 0 +TRAP_ENTRY HalpApcInterrupt, KI_SOFTWARE_TRAP +TRAP_ENTRY HalpDispatchInterrupt, KI_PUSH_FAKE_ERROR_CODE +TRAP_ENTRY HalpClockInterrupt, KI_PUSH_FAKE_ERROR_CODE +TRAP_ENTRY HalpProfileInterrupt, KI_PUSH_FAKE_ERROR_CODE + +FUNC ApicSpuriousService + int 3 + iret +ENDFUNC ApicSpuriousService + + +END
Propchange: trunk/reactos/hal/halx86/apic/apictrap.S ------------------------------------------------------------------------------ svn:eol-style = native
Added: trunk/reactos/hal/halx86/apic/rtctimer.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/hal/halx86/apic/rtctimer.c?... ============================================================================== --- trunk/reactos/hal/halx86/apic/rtctimer.c (added) +++ trunk/reactos/hal/halx86/apic/rtctimer.c [iso-8859-1] Tue Sep 6 21:01:49 2011 @@ -1,0 +1,144 @@ +/* + * PROJECT: ReactOS HAL + * LICENSE: GNU GPL - See COPYING in the top level directory + * FILE: hal/halx86/generic/apic.c + * PURPOSE: HAL APIC Management and Control Code + * PROGRAMMERS: Timo Kreuzer (timo.kreuzer@reactos.org) + * REFERENCES: + */ + +/* INCLUDES *******************************************************************/ + +#include <hal.h> +#define NDEBUG +#include <debug.h> + + +/* GLOBALS ********************************************************************/ + +const UCHAR HalpClockVector = 0xD1; +BOOLEAN HalpClockSetMSRate; +UCHAR HalpNextMSRate; +UCHAR HalpCurrentRate = 9; +ULONG HalpCurrentTimeIncrement; +static UCHAR RtcLargestClockRate = 10; + + +ULONG +FORCEINLINE +RtcClockRateToIncrement(UCHAR Rate) +{ + ULONG Freqency = ((32768 << 1) >> Rate); + return (1000000 + (Freqency/2)) / Freqency; +} + +VOID +RtcSetClockRate(UCHAR ClockRate) +{ + ULONG_PTR EFlags; + UCHAR RegisterA; + + /* Disable interrupts */ + EFlags = __readeflags(); + _disable(); + + // TODO: disable NMI + + /* Read value of register A */ + RegisterA = HalpReadCmos(RTC_REGISTER_A); + + /* Change lower 4 bits to new rate */ + RegisterA &= 0xF0; + RegisterA |= ClockRate; + + /* Write the new value */ + HalpWriteCmos(RTC_REGISTER_A, RegisterA); + + /* Restore interrupts if they were previously enabled */ + __writeeflags(EFlags); +} + + +VOID +NTAPI +INIT_FUNCTION +HalpInitializeClock(VOID) +{ + UCHAR RegisterB; + // TODO: disable NMI + + /* Enable the periodic interrupt in the CMOS */ + RegisterB = HalpReadCmos(RTC_REGISTER_B); + HalpWriteCmos(RTC_REGISTER_B, RegisterB | RTC_REG_B_PI); + + // RtcSetClockRate(HalpCurrentRate); +} + +VOID +FASTCALL +HalpClockInterruptHandler(IN PKTRAP_FRAME TrapFrame) +{ + ULONG LastIncrement; + KIRQL Irql; + + /* Enter trap */ + KiEnterInterruptTrap(TrapFrame); +__debugbreak(); + /* Start the interrupt */ + if (HalBeginSystemInterrupt(CLOCK2_LEVEL, PRIMARY_VECTOR_BASE, &Irql)) + { + /* Read register C, so that the next interrupt can happen */ + HalpReadCmos(RTC_REGISTER_C);; + + /* Save increment */ + LastIncrement = HalpCurrentTimeIncrement; + + /* Check if someone changed the time rate */ + if (HalpClockSetMSRate) + { + /* Update the global values */ + HalpCurrentRate = HalpNextMSRate; + HalpCurrentTimeIncrement = RtcClockRateToIncrement(HalpCurrentRate); + + /* Set new clock rate */ + RtcSetClockRate(HalpCurrentRate); + + /* We're done */ + HalpClockSetMSRate = FALSE; + } + + /* Update the system time -- the kernel will exit this trap */ + KeUpdateSystemTime(TrapFrame, LastIncrement, Irql); + } + + /* Spurious, just end the interrupt */ + KiEoiHelper(TrapFrame); +} + +VOID +FASTCALL +HalpProfileInterruptHandler(IN PKTRAP_FRAME TrapFrame) +{ + __debugbreak(); +} + +ULONG +NTAPI +HalSetTimeIncrement(IN ULONG Increment) +{ + UCHAR Rate; + + /* Lookup largest value below given Increment */ + for (Rate = 2; Rate < RtcLargestClockRate; Rate++) + { + /* Check if this is the largest rate possible */ + if (RtcClockRateToIncrement(Rate + 1) > Increment) break; + } + + /* Set the rate and tell HAL we want to change it */ + HalpNextMSRate = Rate; + HalpClockSetMSRate = TRUE; + + /* Return the real increment */ + return RtcClockRateToIncrement(Rate); +}
Propchange: trunk/reactos/hal/halx86/apic/rtctimer.c ------------------------------------------------------------------------------ svn:eol-style = native
Added: trunk/reactos/hal/halx86/apic/tsc.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/hal/halx86/apic/tsc.c?rev=5... ============================================================================== --- trunk/reactos/hal/halx86/apic/tsc.c (added) +++ trunk/reactos/hal/halx86/apic/tsc.c [iso-8859-1] Tue Sep 6 21:01:49 2011 @@ -1,0 +1,140 @@ +/* + * PROJECT: ReactOS HAL + * LICENSE: GPL - See COPYING in the top level directory + * FILE: hal/halamd64/generic/tsc.c + * PURPOSE: HAL Routines for TSC handling + * PROGRAMMERS: Timo Kreuzer (timo.kreuzer@reactos.org) + */ + +/* INCLUDES ******************************************************************/ + +#include <hal.h> +#define NDEBUG +#include <debug.h> + +#include "tsc.h" + +LARGE_INTEGER HalpCpuClockFrequency = {INITIAL_STALL_COUNT * 1000000}; + +UCHAR TscCalibrationPhase; +LARGE_INTEGER TscCalibrationArray[NUM_SAMPLES]; +extern const UCHAR HalpClockVector; + +/* PRIVATE FUNCTIONS *********************************************************/ + +VOID +NTAPI +HalpInitializeTsc() +{ + ULONG_PTR Flags; + KIDTENTRY OldIdtEntry, *IdtPointer; + PKPCR Pcr = KeGetPcr(); + + /* Check if the CPU supports RDTSC */ + if (!(KeGetCurrentPrcb()->FeatureBits & KF_RDTSC)) + { + KeBugCheck(HAL_INITIALIZATION_FAILED); + } + + /* Save flags and disable interrupts */ + Flags = __readeflags(); + _disable(); + +__debugbreak(); + + /* Initialze the PIT */ + //HalpInitializePIT(); + + /* Save old IDT entry */ + IdtPointer = KiGetIdtEntry(Pcr, HalpClockVector); + OldIdtEntry = *IdtPointer; + + /* Set the calibration ISR */ + KeRegisterInterruptHandler(HalpClockVector, TscCalibrationISR); + + /* Reset TSC value to 0 */ + __writemsr(MSR_RDTSC, 0); + + /* Enable the timer interupt */ + HalEnableSystemInterrupt(HalpClockVector, CLOCK_LEVEL, Latched); + + /* Wait for completion */ + _enable(); + while (TscCalibrationPhase < NUM_SAMPLES) _ReadWriteBarrier(); + _disable(); + + /* Disable the timer interupt */ + HalDisableSystemInterrupt(HalpClockVector, CLOCK_LEVEL); + + /* Restore old IDT entry */ + *IdtPointer = OldIdtEntry; + + // do linear regression + + + /* Restore flags */ + __writeeflags(Flags); + +} + +VOID +NTAPI +HalpCalibrateStallExecution(VOID) +{ + // Timer interrupt is now active + + HalpInitializeTsc(); + + KeGetPcr()->StallScaleFactor = (ULONG)(HalpCpuClockFrequency.QuadPart / 1000000); +} + +/* PUBLIC FUNCTIONS ***********************************************************/ + +LARGE_INTEGER +NTAPI +KeQueryPerformanceCounter( + OUT PLARGE_INTEGER PerformanceFrequency OPTIONAL) +{ + LARGE_INTEGER Result; + + /* Make sure it's calibrated */ + ASSERT(HalpCpuClockFrequency.QuadPart != 0); + + /* Does the caller want the frequency? */ + if (PerformanceFrequency) + { + /* Return tsc frequency */ + *PerformanceFrequency = HalpCpuClockFrequency; + } + + /* Return the current value */ + Result.QuadPart = __rdtsc(); + return Result; +} + +VOID +NTAPI +KeStallExecutionProcessor(ULONG MicroSeconds) +{ + ULONG64 StartTime, EndTime; + + /* Get the initial time */ + StartTime = __rdtsc(); + + /* Calculate the ending time */ + EndTime = StartTime + HalpCpuClockFrequency.QuadPart * MicroSeconds; + + /* Loop until time is elapsed */ + while (__rdtsc() < EndTime); +} + +VOID +NTAPI +HalCalibratePerformanceCounter( + IN volatile PLONG Count, + IN ULONGLONG NewCount) +{ + UNIMPLEMENTED; + ASSERT(FALSE); +} +
Propchange: trunk/reactos/hal/halx86/apic/tsc.c ------------------------------------------------------------------------------ svn:eol-style = native
Added: trunk/reactos/hal/halx86/apic/tsc.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/hal/halx86/apic/tsc.h?rev=5... ============================================================================== --- trunk/reactos/hal/halx86/apic/tsc.h (added) +++ trunk/reactos/hal/halx86/apic/tsc.h [iso-8859-1] Tue Sep 6 21:01:49 2011 @@ -1,0 +1,15 @@ + + +#define NUM_SAMPLES 4 +#define MSR_RDTSC 0x10 + +#ifndef __ASM__ + +void TscCalibrationISR(void); +extern LARGE_INTEGER HalpCpuClockFrequency; +VOID NTAPI HalpInitializeTsc(); + + +#define KiGetIdtEntry(Pcr, Vector) &((Pcr)->IDT[Vector]) + +#endif
Propchange: trunk/reactos/hal/halx86/apic/tsc.h ------------------------------------------------------------------------------ svn:eol-style = native
Added: trunk/reactos/hal/halx86/apic/tsccal.S URL: http://svn.reactos.org/svn/reactos/trunk/reactos/hal/halx86/apic/tsccal.S?re... ============================================================================== --- trunk/reactos/hal/halx86/apic/tsccal.S (added) +++ trunk/reactos/hal/halx86/apic/tsccal.S [iso-8859-1] Tue Sep 6 21:01:49 2011 @@ -1,0 +1,39 @@ + +#include <asm.inc> +#include "tsc.h" + +.code + +EXTERN _TscCalibrationPhase:BYTE +EXTERN _TscCalibrationArray:QWORD + +PUBLIC _TscCalibrationISR +_TscCalibrationISR: + push eax + push ecx + push edx + + /* The first thing we do is read the current TSC value */ + rdtsc + + /* Read the current phase */ + movzx ecx, byte ptr ds:[_TscCalibrationPhase] + + /* Check if we're already done */ + cmp cl, NUM_SAMPLES + jnb _CalibrationISR_Exit + + /* Store the current value */ + mov dword ptr _TscCalibrationArray[ecx * 2], eax + mov dword ptr _TscCalibrationArray[ecx * 2 + 4], edx + + /* Advance phase */ + inc byte ptr ds:[_TscCalibrationPhase] + +_CalibrationISR_Exit: + pop edx + pop ecx + pop eax + iretd + +END
Propchange: trunk/reactos/hal/halx86/apic/tsccal.S ------------------------------------------------------------------------------ svn:eol-style = native