From 0237c83496c2010b76deca387523382dca9d9b8a Mon Sep 17 00:00:00 2001 From: ReactOS Portable Systems Group Date: Tue, 12 Feb 2008 19:01:48 +0000 Subject: [PATCH] QEMU doesn't support TLB Lockdown, so we now use a hack for QEMU and broken CPUs [albeit a portable one ;-)]. PCR access in usermode/kernelmode works. We now have HalSweepI/Dcache APIs exported and stubbed in the ARM HAL (great, since UNIMPLEMENTED macro now works). We now setup more of the PCR, including all the cache values required, then we call the HAL sweep functions (TBD). svn path=/trunk/; revision=32330 --- reactos/hal/hal/hal_arm.def | 2 + reactos/hal/halarm/generic/hal.c | 13 ++++ reactos/ntoskrnl/ke/arm/kiinit.c | 108 ++++++++++++++++++++++++++++--- 3 files changed, 113 insertions(+), 10 deletions(-) diff --git a/reactos/hal/hal/hal_arm.def b/reactos/hal/hal/hal_arm.def index 22459a18af8..3eae6a20af2 100644 --- a/reactos/hal/hal/hal_arm.def +++ b/reactos/hal/hal/hal_arm.def @@ -64,6 +64,8 @@ HalSetTimeIncrement HalStartNextProcessor HalStartProfileInterrupt HalStopProfileInterrupt +HalSweepIcache +HalSweepDcache HalTranslateBusAddress IoAssignDriveLetters=HalpAssignDriveLetters IoFlushAdapterBuffers diff --git a/reactos/hal/halarm/generic/hal.c b/reactos/hal/halarm/generic/hal.c index 465bd8818e9..925ab3a0f6c 100644 --- a/reactos/hal/halarm/generic/hal.c +++ b/reactos/hal/halarm/generic/hal.c @@ -1089,4 +1089,17 @@ KeSwapIrql(IN KIRQL Irql) UNIMPLEMENTED; return 0; } + +VOID +HalSweepDcache(VOID) +{ + UNIMPLEMENTED; +} + +VOID +HalSweepIcache(VOID) +{ + UNIMPLEMENTED; +} + /* EOF */ diff --git a/reactos/ntoskrnl/ke/arm/kiinit.c b/reactos/ntoskrnl/ke/arm/kiinit.c index bf43ddf3ad7..b3bd4a38a28 100644 --- a/reactos/ntoskrnl/ke/arm/kiinit.c +++ b/reactos/ntoskrnl/ke/arm/kiinit.c @@ -19,6 +19,9 @@ ULONG KeFixedTbEntries; ULONG KeNumberProcessIds; ULONG KeNumberTbEntries; +VOID HalSweepDcache(VOID); +VOID HalSweepIcache(VOID); + #define __ARMV6__ KeIsArmV6 // @@ -99,17 +102,34 @@ KeFillFixedEntryTb(IN ARM_PTE Pte, Temp = *(PULONG)Virtual; // - // Read lockdown register and clear the preserve bit + // Read lockdown register // LockdownRegister = KeArmLockdownRegisterGet(); - LockdownRegister.Preserve = FALSE; - ASSERT(LockdownRegister.Victim == OldVictimCount + 1); - KeArmLockdownRegisterSet(LockdownRegister); - - // - // Clear the PTE - // - TranslationTable->Pte[(ULONG)Virtual >> TTB_SHIFT].AsUlong = 0; + if (LockdownRegister.Victim == 0) + { + // + // This can only happen on QEMU or broken CPUs since there *has* + // to have been at least a miss since the system started. For example, + // QEMU doesn't support TLB lockdown. + // + // On these systems, we'll just keep the PTE mapped + // + DPRINT1("TLB Lockdown Failure (%p). Running on QEMU?\n", Virtual); + } + else + { + // + // Clear the preserve bits + // + LockdownRegister.Preserve = FALSE; + ASSERT(LockdownRegister.Victim == OldVictimCount + 1); + KeArmLockdownRegisterSet(LockdownRegister); + + // + // Clear the PTE + // + TranslationTable->Pte[(ULONG)Virtual >> TTB_SHIFT].AsUlong = 0; + } } VOID @@ -188,10 +208,78 @@ KiInitializeSystem(IN ULONG Magic, KeFillFixedEntryTb(Pte, (PVOID)USPCR, PCR_ENTRY + 1); // - // Now we should be able to use the PCR... set the cache policies + // Now we should be able to use the PCR... // Pcr = (PKPCR)KeGetPcr(); + + // + // Set the cache policy (HACK) + // Pcr->CachePolicy = 0; Pcr->AlignedCachePolicy = 0; + + // + // Copy cache information from the loader block + // + Pcr->FirstLevelDcacheSize = LoaderBlock->u.Arm.FirstLevelDcacheSize; + Pcr->SecondLevelDcacheSize = LoaderBlock->u.Arm.SecondLevelDcacheSize; + Pcr->FirstLevelIcacheSize = LoaderBlock->u.Arm.FirstLevelIcacheSize; + Pcr->SecondLevelIcacheSize = LoaderBlock->u.Arm.SecondLevelIcacheSize; + Pcr->FirstLevelDcacheFillSize = LoaderBlock->u.Arm.FirstLevelDcacheFillSize; + Pcr->SecondLevelDcacheFillSize = LoaderBlock->u.Arm.SecondLevelDcacheFillSize; + Pcr->FirstLevelIcacheFillSize = LoaderBlock->u.Arm.FirstLevelIcacheFillSize; + Pcr->SecondLevelIcacheFillSize = LoaderBlock->u.Arm.SecondLevelIcacheFillSize; + + // + // Set global d-cache fill and alignment values + // + if (Pcr->SecondLevelDcacheSize) + { + // + // Use the first level + // + Pcr->DcacheFillSize = Pcr->SecondLevelDcacheSize; + } + else + { + // + // Use the second level + // + Pcr->DcacheFillSize = Pcr->SecondLevelDcacheSize; + } + + // + // Set the alignment + // + Pcr->DcacheAlignment = Pcr->DcacheFillSize - 1; + + // + // Set global i-cache fill and alignment values + // + if (Pcr->SecondLevelIcacheSize) + { + // + // Use the first level + // + Pcr->IcacheFillSize = Pcr->SecondLevelIcacheSize; + } + else + { + // + // Use the second level + // + Pcr->IcacheFillSize = Pcr->SecondLevelIcacheSize; + } + + // + // Set the alignment + // + Pcr->IcacheAlignment = Pcr->IcacheFillSize - 1; + + // + // Now sweep caches + // + HalSweepIcache(); + HalSweepDcache(); while (TRUE); }