- INITIAL_STALL_COUNT makes more sense in decimal (100) than hex (0x64) so define...
authorStefan Ginsberg <stefanginsberg@gmail.com>
Thu, 29 Oct 2009 19:58:41 +0000 (19:58 +0000)
committerStefan Ginsberg <stefanginsberg@gmail.com>
Thu, 29 Oct 2009 19:58:41 +0000 (19:58 +0000)
- Protect CMOS access with the CMOS spinlock.
- Add CMOS initialization to set up the default value of the CMOS century byte offset (not used yet).
- Stub out profile interrupt support in HAL. Register and stub out the profile interrupt handler, but don't handle it yet as vital parts of the rest of the implementation is missing.
- Fix several bugs in the kernel profile implementation:
  - Don't hardcode to PROFILE_LEVEL when raising IRQL : HAL can override this, so use KiProfileIrql. Also, starting/stopping profile interrupts must be done at the profile IRQL, so don't lower it back before calling HAL, which is now enabled.
  - Fix KeSet/QueryIntervalProfile to properly set/query profile intervals through HAL -- pass the correct structures and handle the ProfileAlignmentFixup case properly, and call HAL when setting the timer interval as the interval may be overridden by it.
  - KeStartProfile returns BOOLEAN to tell if the profile was started or not, just like KeStopProfile.
- Make the interrupt implementation more portable for non-PIC architectures.
- Fix HalSystemVectorDispatchEntry; it returns a type (UCHAR), not TRUE/FALSE (BOOLEAN).
- Begin implementing the framework for querying HAL resource usage (keeping track of internal address space and vector registrations/usage).

svn path=/trunk/; revision=43832

22 files changed:
reactos/hal/halamd64/generic/misc.c
reactos/hal/halarm/generic/hal.c
reactos/hal/halppc/generic/misc.c
reactos/hal/halx86/generic/beep.c
reactos/hal/halx86/generic/cmos.c
reactos/hal/halx86/generic/halinit.c
reactos/hal/halx86/generic/misc.c
reactos/hal/halx86/generic/reboot.c
reactos/hal/halx86/generic/sysinfo.c
reactos/hal/halx86/generic/systimer.S
reactos/hal/halx86/include/halp.h
reactos/include/ddk/winddk.h
reactos/include/ndk/amd64/ketypes.h
reactos/include/ndk/arm/ketypes.h
reactos/include/ndk/halfuncs.h
reactos/include/ndk/i386/asm.h
reactos/include/ndk/i386/ketypes.h
reactos/ntoskrnl/fstub/halstub.c
reactos/ntoskrnl/include/internal/hal.h
reactos/ntoskrnl/include/internal/ke.h
reactos/ntoskrnl/ke/i386/irqobj.c
reactos/ntoskrnl/ke/profobj.c

index 7eb1d91..469b820 100644 (file)
@@ -83,7 +83,7 @@ HalHandleNMI(IN PVOID NmiInfo)
 /*
  * @implemented
  */
-BOOLEAN
+UCHAR
 FASTCALL
 HalSystemVectorDispatchEntry(IN ULONG Vector,
                              OUT PKINTERRUPT_ROUTINE **FlatDispatch,
index c35aa0d..43510df 100644 (file)
@@ -857,12 +857,11 @@ HalStartNextProcessor(IN PLOADER_PARAMETER_BLOCK LoaderBlock,
 }
 
 
-ULONG
+UCHAR
 FASTCALL
-HalSystemVectorDispatchEntry(
-  ULONG Unknown1,
-  ULONG Unknown2,
-  ULONG Unknown3)
+HalSystemVectorDispatchEntry(IN ULONG Vector,
+                             OUT PKINTERRUPT_ROUTINE **FlatDispatch,
+                             OUT PKINTERRUPT_ROUTINE *NoConnection)
 {
   UNIMPLEMENTED;
 
index 7eb1d91..469b820 100644 (file)
@@ -83,7 +83,7 @@ HalHandleNMI(IN PVOID NmiInfo)
 /*
  * @implemented
  */
-BOOLEAN
+UCHAR
 FASTCALL
 HalSystemVectorDispatchEntry(IN ULONG Vector,
                              OUT PKINTERRUPT_ROUTINE **FlatDispatch,
index 2bfe8a6..4b82f2b 100644 (file)
@@ -31,9 +31,9 @@ HalMakeBeep(IN ULONG Frequency)
 {
     UCHAR Data;
     ULONG Divider;
-    BOOLEAN Result = TRUE;
 
-    /* FIXME: Acquire CMOS Lock */
+    /* Acquire CMOS Lock */
+    HalpAcquireSystemHardwareSpinLock();
 
     /* Turn the register off */
     Data = READ_PORT_UCHAR(PORT_B);
@@ -49,8 +49,8 @@ HalMakeBeep(IN ULONG Frequency)
         if (Divider > 0x10000)
         {
             /* Fail */
-            Result = FALSE;
-            goto Cleanup;
+            HalpReleaseCmosSpinLock();
+            return FALSE;
         }
 
         /* Set timer divider */
@@ -62,11 +62,9 @@ HalMakeBeep(IN ULONG Frequency)
         WRITE_PORT_UCHAR(PORT_B, READ_PORT_UCHAR(PORT_B) | 0x03);
     }
 
-Cleanup:
-    /* FIXME: Release hardware lock */
+    /* Release CMOS lock */
+    HalpReleaseCmosSpinLock();
 
-    /* Return result */
-    return Result;
+    /* Return success */
+    return TRUE;
 }
-
-
index ed9f1b7..754d360 100644 (file)
@@ -16,6 +16,7 @@
 /* GLOBALS *******************************************************************/
 
 KSPIN_LOCK HalpSystemHardwareLock;
+UCHAR HalpCmosCenturyOffset;
 
 /* PRIVATE FUNCTIONS *********************************************************/
 
@@ -53,13 +54,14 @@ HalpGetCmosData(IN ULONG BusNumber,
     ULONG Address = SlotNumber;
     ULONG Len = Length;
 
-    /* FIXME: Acquire CMOS Lock */
-
     /* Do nothing if we don't have a length */
     if (!Length) return 0;
 
+    /* Acquire CMOS Lock */
+    HalpAcquireSystemHardwareSpinLock();
+
     /* Check if this is simple CMOS */
-    if (!BusNumber)
+    if (BusNumber == 0)
     {
         /* Loop the buffer up to 0xFF */
         while ((Len > 0) && (Address < 0x100))
@@ -88,7 +90,8 @@ HalpGetCmosData(IN ULONG BusNumber,
         }
     }
 
-    /* FIXME: Release the CMOS Lock */
+    /* Release CMOS Lock */
+    HalpReleaseCmosSpinLock();
 
     /* Return length read */
     return Length - Len;
@@ -105,13 +108,14 @@ HalpSetCmosData(IN ULONG BusNumber,
     ULONG Address = SlotNumber;
     ULONG Len = Length;
 
-    /* FIXME: Acquire CMOS Lock */
-
     /* Do nothing if we don't have a length */
     if (!Length) return 0;
 
+    /* Acquire CMOS Lock */
+    HalpAcquireSystemHardwareSpinLock();
+
     /* Check if this is simple CMOS */
-    if (!BusNumber)
+    if (BusNumber == 0)
     {
         /* Loop the buffer up to 0xFF */
         while ((Len > 0) && (Address < 0x100))
@@ -140,12 +144,24 @@ HalpSetCmosData(IN ULONG BusNumber,
         }
     }
 
-    /* FIXME: Release the CMOS Lock */
+    /* Release CMOS Lock */
+    HalpReleaseCmosSpinLock();
 
     /* Return length read */
     return Length - Len;
 }
 
+VOID
+NTAPI
+HalpInitializeCmos(VOID)
+{
+    /* Set default century offset byte */
+    HalpCmosCenturyOffset = 50;
+
+    /* No support for EISA or MCA */
+    ASSERT(HalpBusType == MACHINE_TYPE_ISA);
+}
+
 /* PUBLIC FUNCTIONS **********************************************************/
 
 /*
@@ -162,12 +178,14 @@ HalGetEnvironmentVariable(IN PCH Name,
     /* Only variable supported on x86 */
     if (_stricmp(Name, "LastKnownGood")) return ENOENT;
 
-    /* FIXME: Acquire CMOS Lock */
+    /* Acquire CMOS Lock */
+    HalpAcquireSystemHardwareSpinLock();
 
     /* Query the current value */
     Val = HalpReadCmos(RTC_REGISTER_B) & 0x01;
 
-    /* FIXME: Release CMOS lock */
+    /* Release CMOS lock */
+    HalpReleaseCmosSpinLock();
 
     /* Check the flag */
     if (Val)
@@ -201,14 +219,16 @@ HalSetEnvironmentVariable(IN PCH Name,
     /* Check if this is true or false */
     if (!_stricmp(Value, "TRUE"))
     {
-        /* It's true, acquire CMOS lock (FIXME) */
+        /* It's true, acquire CMOS lock */
+        HalpAcquireSystemHardwareSpinLock();
 
         /* Read the current value and add the flag */
         Val = HalpReadCmos(RTC_REGISTER_B) | 1;
     }
     else if (!_stricmp(Value, "FALSE"))
     {
-        /* It's false, acquire CMOS lock (FIXME) */
+        /* It's false, acquire CMOS lock */
+        HalpAcquireSystemHardwareSpinLock();
 
         /* Read the current value and mask out  the flag */
         Val = HalpReadCmos(RTC_REGISTER_B) & ~1;
@@ -223,6 +243,7 @@ HalSetEnvironmentVariable(IN PCH Name,
     HalpWriteCmos(RTC_REGISTER_B, Val);
 
     /* Release the lock and return success */
+    HalpReleaseCmosSpinLock();
     return ESUCCESS;
 }
 
@@ -233,7 +254,8 @@ BOOLEAN
 NTAPI
 HalQueryRealTimeClock(OUT PTIME_FIELDS Time)
 {
-    /* FIXME: Acquire CMOS Lock */
+    /* Acquire CMOS Lock */
+    HalpAcquireSystemHardwareSpinLock();
 
     /* Loop while update is in progress */
     while ((HalpReadCmos(RTC_REGISTER_A)) & RTC_REG_A_UIP);
@@ -253,7 +275,8 @@ HalQueryRealTimeClock(OUT PTIME_FIELDS Time)
     /* Compensate for the century field */
     Time->Year += (Time->Year > 80) ? 1900: 2000;
 
-    /* FIXME: Release CMOS Lock */
+    /* Release CMOS lock */
+    HalpReleaseCmosSpinLock();
 
     /* Always return TRUE */
     return TRUE;
@@ -266,7 +289,8 @@ BOOLEAN
 NTAPI
 HalSetRealTimeClock(IN PTIME_FIELDS Time)
 {
-    /* FIXME: Acquire CMOS Lock */
+    /* Acquire CMOS Lock */
+    HalpAcquireSystemHardwareSpinLock();
 
     /* Loop while update is in progress */
     while ((HalpReadCmos(RTC_REGISTER_A)) & RTC_REG_A_UIP);
@@ -282,10 +306,9 @@ HalSetRealTimeClock(IN PTIME_FIELDS Time)
 
     /* FIXME: Set the century byte */
 
-    /* FIXME: Release the CMOS Lock */
+    /* Release CMOS lock */
+    HalpReleaseCmosSpinLock();
 
     /* Always return TRUE */
     return TRUE;
 }
-
-/* EOF */
index eeff875..2a8db9d 100644 (file)
@@ -97,11 +97,11 @@ HalInitSystem(IN ULONG BootPhase,
         /* Force initial PIC state */
         KfRaiseIrql(KeGetCurrentIrql());
 
-        /* Setup busy waiting */
-        HalpCalibrateStallExecution();
+        /* Initialize CMOS lock */
+        KeInitializeSpinLock(&HalpSystemHardwareLock);
 
-        /* Initialize the clock */
-        HalpInitializeClock();
+        /* Initialize CMOS */
+        HalpInitializeCmos();
 
         /* Fill out the dispatch tables */
         HalQuerySystemInformation = HaliQuerySystemInformation;
@@ -112,8 +112,27 @@ HalInitSystem(IN ULONG BootPhase,
         HalResetDisplay = HalpBiosDisplayReset;
         HalHaltSystem = HaliHaltSystem;
 
-        /* Initialize the hardware lock (CMOS) */
-        KeInitializeSpinLock(&HalpSystemHardwareLock);
+        /* Register IRQ 2 */
+        HalpRegisterVector(IDT_INTERNAL,
+                           PRIMARY_VECTOR_BASE + 2,
+                           PRIMARY_VECTOR_BASE + 2,
+                           HIGH_LEVEL);
+
+        /* Setup I/O space */
+        HalpDefaultIoSpace.Next = HalpAddressUsageList;
+        HalpAddressUsageList = &HalpDefaultIoSpace;
+
+        /* Setup busy waiting */
+        HalpCalibrateStallExecution();
+
+        /* Initialize the clock */
+        HalpInitializeClock();
+
+        /*
+         * We could be rebooting with a pending profile interrupt,
+         * so clear it here before interrupts are enabled
+         */
+        HalStopProfileInterrupt(ProfileTime);
 
         /* Do some HAL-specific initialization */
         HalpInitPhase0(LoaderBlock);
@@ -123,12 +142,21 @@ HalInitSystem(IN ULONG BootPhase,
         /* Initialize the default HAL stubs for bus handling functions */
         HalpInitNonBusHandler();
 
-        /* Enable the clock interrupt */
-        ((PKIPCR)KeGetPcr())->IDT[0x30].ExtendedOffset =
-            (USHORT)(((ULONG_PTR)HalpClockInterrupt >> 16) & 0xFFFF);
-        ((PKIPCR)KeGetPcr())->IDT[0x30].Offset =
-            (USHORT)((ULONG_PTR)HalpClockInterrupt);
-        HalEnableSystemInterrupt(0x30, CLOCK2_LEVEL, Latched);
+        /* Enable IRQ 0 */
+        HalpEnableInterruptHandler(IDT_DEVICE,
+                                   0,
+                                   PRIMARY_VECTOR_BASE,
+                                   CLOCK2_LEVEL,
+                                   HalpClockInterrupt,
+                                   Latched);
+
+        /* Enable IRQ 8 */
+        HalpEnableInterruptHandler(IDT_DEVICE,
+                                   0,
+                                   PRIMARY_VECTOR_BASE + 8,
+                                   PROFILE_LEVEL,
+                                   HalpProfileInterrupt,
+                                   Latched);
 
         /* Initialize DMA. NT does this in Phase 0 */
         HalpInitDma();
index 7eb1d91..d8710c8 100644 (file)
@@ -83,14 +83,14 @@ HalHandleNMI(IN PVOID NmiInfo)
 /*
  * @implemented
  */
-BOOLEAN
+UCHAR
 FASTCALL
 HalSystemVectorDispatchEntry(IN ULONG Vector,
                              OUT PKINTERRUPT_ROUTINE **FlatDispatch,
                              OUT PKINTERRUPT_ROUTINE *NoConnection)
 {
     /* Not implemented on x86 */
-    return FALSE;
+    return 0;
 }
 
 /*
index 1ba3a3b..510a66d 100644 (file)
@@ -49,10 +49,8 @@ HalpReboot(VOID)
     /* Enable warm reboot */
     ((PUSHORT)ZeroPageMapping)[0x239] = 0x1234;
 
-    /* FIXME: Lock CMOS Access */
-
-    /* Disable interrupts */
-    _disable();
+    /* Lock CMOS Access */
+    HalpAcquireSystemHardwareSpinLock();
 
     /* Setup control register B */
     WRITE_PORT_UCHAR((PUCHAR)0x70, 0x0B);
index b85aead..1bef9c4 100644 (file)
 #include <debug.h>
 
 PUCHAR KdComPortInUse;
+PADDRESS_USAGE HalpAddressUsageList;
+IDTUsageFlags HalpIDTUsageFlags[MAXIMUM_IDTVECTOR];
+IDTUsage HalpIDTUsage[MAXIMUM_IDTVECTOR];
+
+ADDRESS_USAGE HalpDefaultIoSpace =
+{
+    NULL, CmResourceTypePort, IDT_INTERNAL,
+    {
+        {0x2000,  0xC000}, /* PIC?? */
+        {0xC000,  0x1000}, /* DMA 2 */
+        {0x8000,  0x1000}, /* DMA 1 */
+        {0x2000,  0x200},  /* PIC 1 */
+        {0xA000,  0x200},  /* PIC 2 */
+        {0x4000,  0x400},  /* PIT 1 */
+        {0x4800,  0x400},  /* PIT 2 */
+        {0x9200,  0x100},  /* ????? */
+        {0x7000,  0x200},  /* CMOS  */
+        {0xF000,  0x1000}, /* ????? */
+        {0xCF800, 0x800},  /* PCI 0 */
+        {0,0},
+    }
+};
 
 /* FUNCTIONS *****************************************************************/
 
 NTSTATUS
 NTAPI
-HaliQuerySystemInformation(IN     HAL_QUERY_INFORMATION_CLASS InformationClass,
-                           IN     ULONG  BufferSize,
-                           IN OUT PVOID  Buffer,
-                              OUT PULONG ReturnedLength)
+HaliQuerySystemInformation(IN HAL_QUERY_INFORMATION_CLASS InformationClass,
+                           IN ULONG BufferSize,
+                           IN OUT PVOID Buffer,
+                           OUT PULONG ReturnedLength)
 {
 #define REPORT_THIS_CASE(X) case X: DPRINT1("Unhandled case: %s\n", #X); break
        switch (InformationClass)
@@ -68,4 +90,44 @@ HaliSetSystemInformation(IN HAL_SET_INFORMATION_CLASS InformationClass,
     return STATUS_NOT_IMPLEMENTED;
 }
 
+VOID
+NTAPI
+HalpRegisterVector(IN UCHAR Flags,
+                   IN ULONG BusVector,
+                   IN ULONG SystemVector,
+                   IN KIRQL Irql)
+{
+    /* Save the vector flags */
+    HalpIDTUsageFlags[SystemVector].Flags = Flags;
+
+    /* Save the vector data */
+    HalpIDTUsage[SystemVector].Irql  = Irql;
+    HalpIDTUsage[SystemVector].BusReleativeVector = BusVector;
+}
+
+VOID
+NTAPI
+HalpEnableInterruptHandler(IN UCHAR Flags,
+                           IN ULONG BusVector,
+                           IN ULONG SystemVector,
+                           IN KIRQL Irql,
+                           IN PVOID Handler,
+                           IN KINTERRUPT_MODE Mode)
+{
+    UCHAR Entry;
+
+    /* Convert the vector into the IDT entry */
+    Entry = HalVectorToIDTEntry(SystemVector);
+
+    /* Register the vector */
+    HalpRegisterVector(Flags, BusVector, SystemVector, Irql);
+
+    /* Connect the interrupt */
+    ((PKIPCR)KeGetPcr())->IDT[Entry].ExtendedOffset = (USHORT)(((ULONG_PTR)Handler >> 16) & 0xFFFF);
+    ((PKIPCR)KeGetPcr())->IDT[Entry].Offset = (USHORT)((ULONG_PTR)Handler);
+
+    /* Enable the interrupt */
+    HalEnableSystemInterrupt(SystemVector, Irql, Mode);
+}
+
 /* EOF */
index 7853d51..62f11c1 100644 (file)
@@ -17,7 +17,6 @@ _HalpLastPerfCounterLow:    .long 0
 _HalpLastPerfCounterHigh:   .long 0
 _HalpPerfCounterLow:        .long 0
 _HalpPerfCounterHigh:       .long 0
-_HalpSystemHardwareLock:    .long 0
 _HalpSystemHardwareFlags:   .long 0
 
 _UnhandledMsg:
@@ -52,6 +51,7 @@ _HalpReleaseCmosSpinLock@0:
     popf
     ret
 #endif
+
 .endfunc
 
 .global _HalpAcquireSystemHardwareSpinLock@0
@@ -84,7 +84,6 @@ CmosSpin:
 
     /* Spin */
     SPIN_ON_LOCK(eax, HardwareLock)
-
 #else
     /* Save EFLAGS, disable interrupts and return */
     pushf
@@ -92,6 +91,7 @@ CmosSpin:
     pop _HalpSystemHardwareFlags
     ret
 #endif
+
 .endfunc
 
 .global _HalpCalibrateStallExecution@0
@@ -632,3 +632,28 @@ Spurious:
     jmp _Kei386EoiHelper@0
 .endfunc
 
+.globl _HalpProfileInterrupt@0
+.func HalpProfileInterrupt@0
+TRAP_FIXUPS hpi_a, hpi_t, DoFixupV86, DoFixupAbios
+_HalpProfileInterrupt@0:
+
+    /* Enter trap */
+    INT_PROLOG hpi_a, hpi_t, DoPushFakeErrorCode
+
+    /* Push vector and make stack for IRQL */
+    push 0x38
+    sub esp, 4
+
+    /* Begin the interrupt */
+    push esp
+    push 0x38
+    push PROFILE_LEVEL
+    call _HalBeginSystemInterrupt@12
+
+    /* Check if it's spurious */
+    or al, al
+    jz Spurious
+
+    /* FIXME: We should not be getting profile interrupts yet! */
+    int 3
+.endfunc
index 3a5939f..bd5f61e 100644 (file)
 #define TIMER_BOTH              0x30
 #define TIMER_MD2               0x4
 
+/* Usage flags */
+#define IDT_REGISTERED          0x01
+#define IDT_LATCHED             0x02
+#define IDT_INTERNAL            0x11
+#define IDT_DEVICE              0x21
+
 /* Conversion functions */
 #define BCD_INT(bcd)            \
     (((bcd & 0xF0) >> 4) * 10 + (bcd & 0x0F))
 #define INT_BCD(int)            \
     (UCHAR)(((int / 10) << 4) + (int % 10))
 
+typedef struct _IDTUsageFlags
+{
+    UCHAR Flags;
+} IDTUsageFlags;
+
+typedef struct
+{
+    KIRQL Irql;
+    UCHAR BusReleativeVector;
+} IDTUsage;
+
+typedef struct _HalAddressUsage
+{
+    struct _HalAddressUsage *Next;
+    CM_RESOURCE_TYPE Type;
+    UCHAR Flags;
+    struct
+    {
+        ULONG Start;
+        ULONG Length;
+    } Element[];
+} ADDRESS_USAGE, *PADDRESS_USAGE;
+
 /* adapter.c */
 PADAPTER_OBJECT NTAPI HalpAllocateAdapterEx(ULONG NumberOfMapRegisters,BOOLEAN IsMaster, BOOLEAN Dma32BitAddresses);
 
 /* bus.c */
 VOID NTAPI HalpInitNonBusHandler (VOID);
 
+/* sysinfo.c */
+VOID
+NTAPI
+HalpRegisterVector(IN UCHAR Flags,
+                   IN ULONG BusVector,
+                   IN ULONG SystemVector,
+                   IN KIRQL Irql);
+
+VOID
+NTAPI
+HalpEnableInterruptHandler(IN UCHAR Flags,
+                           IN ULONG BusVector,
+                           IN ULONG SystemVector,
+                           IN KIRQL Irql,
+                           IN PVOID Handler,
+                           IN KINTERRUPT_MODE Mode);
+
 /* irql.c */
 VOID NTAPI HalpInitPICs(VOID);
 
@@ -45,12 +91,6 @@ VOID
 NTAPI
 HalpCalibrateStallExecution(VOID);
 
-ULONG
-NTAPI
-HalpQuery8254Counter(
-    VOID
-);
-
 /* pci.c */
 VOID HalpInitPciBus (VOID);
 
@@ -61,6 +101,7 @@ VOID HalpInitDma (VOID);
 VOID HalpInitPhase0 (PLOADER_PARAMETER_BLOCK LoaderBlock);
 VOID HalpInitPhase1(VOID);
 VOID NTAPI HalpClockInterrupt(VOID);
+VOID NTAPI HalpProfileInterrupt(VOID);
 
 //
 // KD Support
@@ -173,6 +214,30 @@ HaliHaltSystem(
     VOID
 );
 
+//
+// CMOS initialization
+//
+VOID
+NTAPI
+HalpInitializeCmos(
+    VOID
+);
+
+//
+// Spinlock for protecting CMOS access
+//
+VOID
+NTAPI
+HalpAcquireSystemHardwareSpinLock(
+    VOID
+);
+
+VOID
+NTAPI
+HalpReleaseCmosSpinLock(
+    VOID
+);
+
 #ifdef _M_AMD64
 #define KfLowerIrql KeLowerIrql
 #ifndef CONFIG_SMP
@@ -187,6 +252,10 @@ HaliHaltSystem(
 extern PVOID HalpRealModeStart;
 extern PVOID HalpRealModeEnd;
 
+extern ADDRESS_USAGE HalpDefaultIoSpace;
+
 extern KSPIN_LOCK HalpSystemHardwareLock;
 
+extern PADDRESS_USAGE HalpAddressUsageList;
+
 #endif /* __INTERNAL_HAL_HAL_H */
index b9902b9..2bbe95b 100644 (file)
@@ -2433,6 +2433,34 @@ typedef struct _ARBITER_INTERFACE {
   ULONG  Flags;
 } ARBITER_INTERFACE, *PARBITER_INTERFACE;
 
+typedef enum _KPROFILE_SOURCE {
+  ProfileTime,
+  ProfileAlignmentFixup,
+  ProfileTotalIssues,
+  ProfilePipelineDry,
+  ProfileLoadInstructions,
+  ProfilePipelineFrozen,
+  ProfileBranchInstructions,
+  ProfileTotalNonissues,
+  ProfileDcacheMisses,
+  ProfileIcacheMisses,
+  ProfileCacheMisses,
+  ProfileBranchMispredictions,
+  ProfileStoreInstructions,
+  ProfileFpInstructions,
+  ProfileIntegerInstructions,
+  Profile2Issue,
+  Profile3Issue,
+  Profile4Issue,
+  ProfileSpecialInstructions,
+  ProfileTotalCycles,
+  ProfileIcacheIssues,
+  ProfileDcacheAccesses,
+  ProfileMemoryBarrierCycles,
+  ProfileLoadLinkedIssues,
+  ProfileMaximum
+} KPROFILE_SOURCE;
+
 typedef enum _HAL_QUERY_INFORMATION_CLASS {
   HalInstalledBusInformation,
   HalProfileSourceInformation,
@@ -2470,6 +2498,19 @@ typedef enum _HAL_SET_INFORMATION_CLASS {
   HalGenerateCmcInterrupt
 } HAL_SET_INFORMATION_CLASS, *PHAL_SET_INFORMATION_CLASS;
 
+typedef struct _HAL_PROFILE_SOURCE_INTERVAL
+{
+    KPROFILE_SOURCE Source;
+    ULONG_PTR Interval;
+} HAL_PROFILE_SOURCE_INTERVAL, *PHAL_PROFILE_SOURCE_INTERVAL;
+
+typedef struct _HAL_PROFILE_SOURCE_INFORMATION
+{
+    KPROFILE_SOURCE Source;
+    BOOLEAN Supported;
+    ULONG Interval;
+} HAL_PROFILE_SOURCE_INFORMATION, *PHAL_PROFILE_SOURCE_INFORMATION;
+
 typedef struct _MAP_REGISTER_ENTRY
 {
     PVOID MapRegister;
@@ -4269,34 +4310,6 @@ typedef VOID
 (DDKAPI *PKINTERRUPT_ROUTINE)(
   VOID);
 
-typedef enum _KPROFILE_SOURCE {
-  ProfileTime,
-  ProfileAlignmentFixup,
-  ProfileTotalIssues,
-  ProfilePipelineDry,
-  ProfileLoadInstructions,
-  ProfilePipelineFrozen,
-  ProfileBranchInstructions,
-  ProfileTotalNonissues,
-  ProfileDcacheMisses,
-  ProfileIcacheMisses,
-  ProfileCacheMisses,
-  ProfileBranchMispredictions,
-  ProfileStoreInstructions,
-  ProfileFpInstructions,
-  ProfileIntegerInstructions,
-  Profile2Issue,
-  Profile3Issue,
-  Profile4Issue,
-  ProfileSpecialInstructions,
-  ProfileTotalCycles,
-  ProfileIcacheIssues,
-  ProfileDcacheAccesses,
-  ProfileMemoryBarrierCycles,
-  ProfileLoadLinkedIssues,
-  ProfileMaximum
-} KPROFILE_SOURCE;
-
 typedef enum _CREATE_FILE_TYPE {
   CreateFileTypeNone,
   CreateFileTypeNamedPipe,
index 733996f..03ee79c 100644 (file)
@@ -116,7 +116,7 @@ Author:
 //
 // HAL Variables
 //
-#define INITIAL_STALL_COUNT     0x64
+#define INITIAL_STALL_COUNT     100
 
 //
 // IOPM Definitions
index e38d13d..587e1b6 100644 (file)
@@ -47,7 +47,7 @@ Author:
 //
 // HAL Variables
 //
-#define INITIAL_STALL_COUNT     0x64
+#define INITIAL_STALL_COUNT     100
 
 //
 // Static Kernel-Mode Address start (use MM_KSEG0_BASE for actual)
index d010fcc..7e31815 100644 (file)
@@ -203,6 +203,15 @@ HalHandleNMI(
     PVOID NmiInfo
 );
 
+NTHALAPI
+UCHAR
+FASTCALL
+HalSystemVectorDispatchEntry(
+    IN ULONG Vector,
+    OUT PKINTERRUPT_ROUTINE **FlatDispatch,
+    OUT PKINTERRUPT_ROUTINE *NoConnection
+);
+
 //
 // Environment Functions
 //
@@ -225,6 +234,29 @@ HalGetEnvironmentVariable(
 );
 #endif
 
+//
+// Profiling Functions
+//
+VOID
+NTAPI
+HalStartProfileInterrupt(
+    IN KPROFILE_SOURCE ProfileSource
+);
+
+NTHALAPI
+VOID
+NTAPI
+HalStopProfileInterrupt(
+    IN KPROFILE_SOURCE ProfileSource
+);
+
+NTHALAPI
+ULONG_PTR
+NTAPI
+HalSetProfileInterval(
+    IN ULONG_PTR Interval
+);
+
 //
 // Time Functions
 //
index 18908cc..095cb5d 100644 (file)
@@ -588,6 +588,7 @@ Author:
 #define PASSIVE_LEVEL                           0x0
 #define APC_LEVEL                               0x1
 #define DISPATCH_LEVEL                          0x2
+#define PROFILE_LEVEL                           0x1B
 #define CLOCK2_LEVEL                            0x1C
 #define IPI_LEVEL                               0x1D
 #define HIGH_LEVEL                              0x1F
index 4ce9818..78b47c4 100644 (file)
@@ -124,7 +124,7 @@ Author:
 //
 // HAL Variables
 //
-#define INITIAL_STALL_COUNT     0x64
+#define INITIAL_STALL_COUNT     100
 
 //
 // IOPM Definitions
index 0254e92..a646945 100644 (file)
@@ -59,13 +59,21 @@ HAL_PRIVATE_DISPATCH HalPrivateDispatchTable =
     (pKdReleasePciDeviceForDebugging)NULL,
     (pKdGetAcpiTablePhase0)NULL,
     (pKdCheckPowerButton)NULL,
-    (pHalVectorToIDTEntry)NULL,
+    (pHalVectorToIDTEntry)xHalVectorToIDTEntry,
     (pKdMapPhysicalMemory64)NULL,
     (pKdUnmapVirtualAddress)NULL
 };
 
 /* FUNCTIONS *****************************************************************/
 
+UCHAR
+NTAPI
+xHalVectorToIDTEntry(IN ULONG Vector)
+{
+    /* Return the vector */
+    return Vector;
+}
+
 VOID
 NTAPI
 xHalHaltSystem(VOID)
index ff9462c..32638d2 100644 (file)
@@ -53,6 +53,12 @@ xHalHaltSystem(
     VOID
 );
 
+UCHAR
+NTAPI
+xHalVectorToIDTEntry(
+    IN ULONG Vector
+);
+
 
 //
 // Various offsets in the boot record
index 4173a3a..f512e2f 100644 (file)
@@ -403,7 +403,7 @@ KeInitializeProfile(
     KAFFINITY Affinity
 );
 
-VOID
+BOOLEAN
 NTAPI
 KeStartProfile(
     struct _KPROFILE* Profile,
index b22c381..63520d8 100644 (file)
@@ -46,10 +46,21 @@ KiGetVectorDispatch(IN ULONG Vector,
 {
     PKINTERRUPT_ROUTINE Handler;
     ULONG Current;
+    UCHAR Type;
+    UCHAR Entry;
+
+    /* Check if this is a primary or 2nd-level dispatch */
+    Type = HalSystemVectorDispatchEntry(Vector,
+                                        &Dispatch->FlatDispatch,
+                                        &Dispatch->NoDispatch);
+    ASSERT(Type == 0);
+
+    /* Get the IDT entry for this vector */
+    Entry = HalVectorToIDTEntry(Vector);
 
     /* Setup the unhandled dispatch */
     Dispatch->NoDispatch = (PVOID)(((ULONG_PTR)&KiStartUnexpectedRange) +
-                                   (Vector - PRIMARY_VECTOR_BASE) *
+                                   (Entry - PRIMARY_VECTOR_BASE) *
                                    KiUnexpectedEntrySize);
 
     /* Setup the handlers */
@@ -59,9 +70,9 @@ KiGetVectorDispatch(IN ULONG Vector,
     Dispatch->FlatDispatch = NULL;
 
     /* Get the current handler */
-    Current = ((((PKIPCR)KeGetPcr())->IDT[Vector].ExtendedOffset << 16)
+    Current = ((((PKIPCR)KeGetPcr())->IDT[Entry].ExtendedOffset << 16)
                & 0xFFFF0000) |
-              (((PKIPCR)KeGetPcr())->IDT[Vector].Offset & 0xFFFF);
+              (((PKIPCR)KeGetPcr())->IDT[Entry].Offset & 0xFFFF);
 
     /* Set the interrupt */
     Dispatch->Interrupt = CONTAINING_RECORD(Current,
@@ -105,6 +116,7 @@ KiConnectVectorToInterrupt(IN PKINTERRUPT Interrupt,
     DISPATCH_INFO Dispatch;
     PKINTERRUPT_ROUTINE Handler;
     PULONG Patch = &Interrupt->DispatchCode[0];
+    UCHAR Entry;
 
     /* Get vector data */
     KiGetVectorDispatch(Interrupt->Vector, &Dispatch);
@@ -139,10 +151,13 @@ KiConnectVectorToInterrupt(IN PKINTERRUPT Interrupt,
         Handler = (PVOID)&Interrupt->DispatchCode;
     }
 
+    /* Get the IDT entry for this vector */
+    Entry = HalVectorToIDTEntry(Interrupt->Vector);
+
     /* Set the pointer in the IDT */
-    ((PKIPCR)KeGetPcr())->IDT[Interrupt->Vector].ExtendedOffset =
+    ((PKIPCR)KeGetPcr())->IDT[Entry].ExtendedOffset =
         (USHORT)(((ULONG_PTR)Handler >> 16) & 0xFFFF);
-    ((PKIPCR)KeGetPcr())->IDT[Interrupt->Vector].Offset =
+    ((PKIPCR)KeGetPcr())->IDT[Entry].Offset =
         (USHORT)PtrToUlong(Handler);
 }
 
index cd46580..6347c03 100644 (file)
@@ -19,6 +19,7 @@ LIST_ENTRY KiProfileListHead;
 LIST_ENTRY KiProfileSourceListHead;
 KSPIN_LOCK KiProfileLock;
 ULONG KiProfileTimeInterval = 78125; /* Default resolution 7.8ms (sysinternals) */
+ULONG KiProfileAlignmentFixupInterval;
 
 /* FUNCTIONS *****************************************************************/
 
@@ -46,27 +47,27 @@ KeInitializeProfile(PKPROFILE Profile,
     Profile->Affinity = Affinity;
 }
 
-VOID
+BOOLEAN
 NTAPI
-KeStartProfile(PKPROFILE Profile,
-               PVOID Buffer)
+KeStartProfile(IN PKPROFILE Profile,
+               IN PVOID Buffer)
 {
     KIRQL OldIrql;
     PKPROFILE_SOURCE_OBJECT SourceBuffer;
     PKPROFILE_SOURCE_OBJECT CurrentSource;
-    BOOLEAN FreeBuffer = TRUE, SourceFound = FALSE;
+    BOOLEAN FreeBuffer = TRUE, SourceFound = FALSE, StartedProfile;
     PKPROCESS ProfileProcess;
     PLIST_ENTRY NextEntry;
 
     /* Allocate a buffer first, before we raise IRQL */
     SourceBuffer = ExAllocatePoolWithTag(NonPagedPool,
-                                          sizeof(KPROFILE_SOURCE_OBJECT),
-                                          'forP');
-    if (!SourceBuffer) return;
+                                         sizeof(KPROFILE_SOURCE_OBJECT),
+                                         'forP');
+    if (!SourceBuffer) return FALSE;
     RtlZeroMemory(SourceBuffer, sizeof(KPROFILE_SOURCE_OBJECT));
 
-    /* Raise to PROFILE_LEVEL */
-    KeRaiseIrql(PROFILE_LEVEL, &OldIrql);
+    /* Raise to profile IRQL and acquire the profile lock */
+    KeRaiseIrql(KiProfileIrql, &OldIrql);
     KeAcquireSpinLockAtDpcLevel(&KiProfileLock);
 
     /* Make sure it's not running */
@@ -75,6 +76,7 @@ KeStartProfile(PKPROFILE Profile,
         /* Set it as Started */
         Profile->Buffer = Buffer;
         Profile->Started = TRUE;
+        StartedProfile = TRUE;
 
         /* Get the process, if any */
         ProfileProcess = Profile->Process;
@@ -124,29 +126,39 @@ KeStartProfile(PKPROFILE Profile,
             FreeBuffer = FALSE;
         }
     }
+    else
+    {
+        /* Already running so nothing to start */
+        StartedProfile = FALSE;
+    }
 
-    /* Lower the IRQL */
+    /* Release the profile lock */
     KeReleaseSpinLockFromDpcLevel(&KiProfileLock);
-    KeLowerIrql(OldIrql);
 
-    /* FIXME: Tell HAL to Start the Profile Interrupt */
-    //HalStartProfileInterrupt(Profile->Source);
+    /* Tell HAL to start the profile interrupt */
+    HalStartProfileInterrupt(Profile->Source);
+
+    /* Lower back to original IRQL */
+    KeLowerIrql(OldIrql);
 
     /* Free the pool */
     if (FreeBuffer) ExFreePool(SourceBuffer);
+
+    /* Return whether we could start the profile */
+    return StartedProfile;
 }
 
 BOOLEAN
 NTAPI
-KeStopProfile(PKPROFILE Profile)
+KeStopProfile(IN PKPROFILE Profile)
 {
     KIRQL OldIrql;
     PKPROFILE_SOURCE_OBJECT CurrentSource = NULL;
     PLIST_ENTRY NextEntry;
-    BOOLEAN SourceFound = FALSE;
+    BOOLEAN SourceFound = FALSE, StoppedProfile;
 
-    /* Raise to PROFILE_LEVEL and acquire spinlock */
-    KeRaiseIrql(PROFILE_LEVEL, &OldIrql);
+    /* Raise to profile IRQL and acquire the profile lock */
+    KeRaiseIrql(KiProfileIrql, &OldIrql);
     KeAcquireSpinLockAtDpcLevel(&KiProfileLock);
 
     /* Make sure it's running */
@@ -155,6 +167,7 @@ KeStopProfile(PKPROFILE Profile)
         /* Remove it from the list and disable */
         RemoveEntryList(&Profile->ProfileListEntry);
         Profile->Started = FALSE;
+        StoppedProfile = TRUE;
 
         /* Start looping */
         for (NextEntry = KiProfileSourceListHead.Flink;
@@ -179,60 +192,99 @@ KeStopProfile(PKPROFILE Profile)
         }
 
     }
+    else
+    {
+        /* It wasn't! */
+        StoppedProfile = FALSE;
+    }
 
-    /* Lower IRQL */
+    /* Release the profile lock */
     KeReleaseSpinLockFromDpcLevel(&KiProfileLock);
-    KeLowerIrql(OldIrql);
 
-    /* Stop Profiling. FIXME: Implement in HAL */
-    //HalStopProfileInterrupt(Profile->Source);
+    /* Stop the profile interrupt */
+    HalStopProfileInterrupt(Profile->Source);
+
+    /* Lower back to original IRQL */
+    KeLowerIrql(OldIrql);
 
     /* Free the Source Object */
     if (SourceFound) ExFreePool(CurrentSource);
 
-    /* FIXME */
-    return FALSE;
+    /* Return whether we could stop the profile */
+    return StoppedProfile;
 }
 
 ULONG
 NTAPI
-KeQueryIntervalProfile(KPROFILE_SOURCE ProfileSource)
+KeQueryIntervalProfile(IN KPROFILE_SOURCE ProfileSource)
 {
-    /* Check if this is the timer profile */
+    HAL_PROFILE_SOURCE_INFORMATION ProfileSourceInformation;
+    ULONG ReturnLength, Interval;
+    NTSTATUS Status;
+
+    /* Check what profile this is */
     if (ProfileSource == ProfileTime)
     {
-        /* Return the good old 100ns sampling interval */
-        return KiProfileTimeInterval;
+        /* Return the time interval */
+        Interval = KiProfileTimeInterval;
+    }
+    else if (ProfileSource == ProfileAlignmentFixup)
+    {
+        /* Return the alignment interval */
+        Interval = KiProfileAlignmentFixupInterval;
     }
     else
     {
-        /* Request it from HAL. FIXME: What structure is used? */
-        HalQuerySystemInformation(HalProfileSourceInformation,
-                                  sizeof(NULL),
-                                  NULL,
-                                  NULL);
-
-        return 0;
+        /* Request it from HAL */
+        ProfileSourceInformation.Source = ProfileSource;
+        Status = HalQuerySystemInformation(HalProfileSourceInformation,
+                                           sizeof(HAL_PROFILE_SOURCE_INFORMATION),
+                                           &ProfileSourceInformation,
+                                           &ReturnLength);
+
+        /* Check if HAL handled it and supports this profile */
+        if (NT_SUCCESS(Status) && (ProfileSourceInformation.Supported))
+        {
+            /* Get the interval */
+            Interval = ProfileSourceInformation.Interval;
+        }
+        else
+        {
+            /* Unsupported or invalid source, fail */
+            Interval = 0;
+        }
     }
+
+    /* Return the interval we got */
+    return Interval;
 }
 
 VOID
 NTAPI
-KeSetIntervalProfile(KPROFILE_SOURCE ProfileSource,
-                     ULONG Interval)
+KeSetIntervalProfile(IN KPROFILE_SOURCE ProfileSource,
+                     IN ULONG Interval)
 {
-    /* Check if this is the timer profile */
+    HAL_PROFILE_SOURCE_INTERVAL ProfileSourceInterval;
+
+    /* Check what profile this is */
     if (ProfileSource == ProfileTime)
     {
-        /* Set the good old 100ns sampling interval */
-        KiProfileTimeInterval = Interval;
+        /* Set the interval through HAL */
+        KiProfileTimeInterval = HalSetProfileInterval(Interval);
+    }
+    else if (ProfileSource == ProfileAlignmentFixup)
+    {
+        /* Set the alignment interval */
+        KiProfileAlignmentFixupInterval = Interval;
     }
     else
     {
-        /* Set it with HAL. FIXME: What structure is used? */
-        HalSetSystemInformation(HalProfileSourceInformation,
-                                  sizeof(NULL),
-                                  NULL);
+        /* HAL handles any other interval */
+        ProfileSourceInterval.Source = ProfileSource;
+        ProfileSourceInterval.Interval = Interval;
+        HalSetSystemInformation(HalProfileSourceInterval,
+                                sizeof(HAL_PROFILE_SOURCE_INTERVAL),
+                                &ProfileSourceInterval);
     }
 }
 
@@ -241,7 +293,7 @@ KeSetIntervalProfile(KPROFILE_SOURCE ProfileSource,
  */
 VOID
 NTAPI
-KeProfileInterrupt(PKTRAP_FRAME TrapFrame)
+KeProfileInterrupt(IN PKTRAP_FRAME TrapFrame)
 {
     /* Called from HAL for Timer Profiling */
     KeProfileInterruptWithSource(TrapFrame, ProfileTime);