Author: ros-arm-bringup Date: Mon Mar 10 12:27:14 2008 New Revision: 32640
URL: http://svn.reactos.org/svn/reactos?rev=3D32640&view=3Drev Log: ARM Port Memory Management Checkpoint: - Implemented and defined the MMU-OS architecture for the ARM port. The det= ails are too long for a commit message, but we have decided to replicate th= e x86 NT memory manager layout. We've defined a PTE_BASE at 0xC0000000 just= like on x86, and we use a PDE_BASE at 0xC1000000. Unlike the x86, we can't= use PDE-PTE self-mapping because ARM has different formats (and sizes!) fo= r PDE vs PTEs! We emulate the behavior however (which adds a small performa= nce hit) and the Mm porting is thus at least 10 times easier. - Moved serial port to 0xE0000000 for now. - We now parse the board memory map from u-boot. - Added memory allocation code to FreeLDR -- we now build a full ARC memory= map for the kernel. - FreeLDR allocates page tables and sets up the initial support for our mem= ory layout (see comments for some lengthier explenations) - Allocations made by FreeLDR for loading ReactOS are now made from a "shar= ed heap" page that's also marked in the memory map. - Registry and NLS data are now being put into the loader block. - We now create a loader entry for the kernel (but not anything else -- we'= ll have to parse the list properly later). - Defined correct _HARDWARE_PTE_ARM and _MMPTE_HARDWARE for ARM. - ARM_COARSE_PAGE_TABLE is now 4KB instead of 1KB, going against the archit= ecture! We do this for proper OS support of the PTE_BASE. - Fixed build due to KiSystemStartulReal change. - Fixed a bug on the x86 build when creating memory allocation descriptors.= Memory corruption could occur in certain scenarios. - Implemented significant portions of the ARM memory manager code in the ke= rnel: - MmGetPageDirectory. - MmDeletePageTable (for the kernel address space only). - MmIsPagePresent (for the kernel address space only). - MmCreateVirtualMappingForKernel. - MmCreateVirtualMapping (calls MmCreateVirtualMappingUnsafe). - MmCreateVirtualMappingUnsafe (for the kernel address space only). - MmSetPageProtect (unused on ARM). - MmCreateHyperspaceMapping. - MmDeleteHyperspaceMapping. - MmInitGlobalKernelPageDirectory. - MmInitPageDirectoryMap. - With the above, this means we now go well inside MmInit1: the PFN databas= e is setup and works, memory areas are functional, and non-paged pool is fu= lly working. - We currently hit a data abort during paged pool setup -- this is to be ex= pected, since we don't have any exception handlers yet. These are coming up= next -- we have to start handling crashes (and page faults).
Modified: trunk/reactos/boot/freeldr/freeldr/arch/arm/boot.s trunk/reactos/boot/freeldr/freeldr/arch/arm/loader.c trunk/reactos/boot/freeldr/freeldr/arch/arm/macharm.c trunk/reactos/boot/freeldr/freeldr/reactos/imageldr.c trunk/reactos/include/ndk/arm/mmtypes.h trunk/reactos/ntoskrnl/include/internal/arm/ke.h trunk/reactos/ntoskrnl/include/internal/arm/mm.h trunk/reactos/ntoskrnl/ke/arm/arm_kprintf.c trunk/reactos/ntoskrnl/ke/freeldr.c trunk/reactos/ntoskrnl/mm/arm/stubs.c trunk/reactos/ntoskrnl/mm/mminit.c
Modified: trunk/reactos/boot/freeldr/freeldr/arch/arm/boot.s URL: http://svn.reactos.org/svn/reactos/trunk/reactos/boot/freeldr/freeldr/= arch/arm/boot.s?rev=3D32640&r1=3D32639&r2=3D32640&view=3Ddiff =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D --- trunk/reactos/boot/freeldr/freeldr/arch/arm/boot.s (original) +++ trunk/reactos/boot/freeldr/freeldr/arch/arm/boot.s Mon Mar 10 12:27:14 = 2008 @@ -61,12 +61,16 @@ .long ArmInit =
.align 4 +.global BootStack BootStack: .space 0x4000 BootStackEnd: .long 0 =
.section pagedata +.global TranslationTableStart +TranslationTableStart: + .global ArmTranslationTable ArmTranslationTable: .space 0x4000 // 0x00000000->0xFFFFFFFF @@ -74,19 +78,81 @@ .global BootTranslationTable BootTranslationTable: .space 0x0400 // 0x00000000->0x800FFFFF + .space 0x0C00 // PADDING FOR 4KB GRANULARITY .space 0x0400 // 0x00100000->0x801FFFFF + .space 0x0C00 // PADDING FOR 4KB GRANULARITY .space 0x0400 // 0x00200000->0x802FFFFF + .space 0x0C00 // PADDING FOR 4KB GRANULARITY .space 0x0400 // 0x00300000->0x803FFFFF + .space 0x0C00 // PADDING FOR 4KB GRANULARITY .space 0x0400 // 0x00400000->0x804FFFFF + .space 0x0C00 // PADDING FOR 4KB GRANULARITY .space 0x0400 // 0x00500000->0x805FFFFF + .space 0x0C00 // PADDING FOR 4KB GRANULARITY .space 0x0400 // 0x00600000->0x806FFFFF + .space 0x0C00 // PADDING FOR 4KB GRANULARITY .space 0x0400 // 0x00700000->0x807FFFFF + .space 0x0C00 // PADDING FOR 4KB GRANULARITY =
.global KernelTranslationTable KernelTranslationTable: .space 0x0400 // 0x00800000->0x808FFFFF + .space 0x0C00 // PADDING FOR 4KB GRANULARITY .space 0x0400 // 0x00900000->0x809FFFFF + .space 0x0C00 // PADDING FOR 4KB GRANULARITY .space 0x0400 // 0x00A00000->0x80AFFFFF + .space 0x0C00 // PADDING FOR 4KB GRANULARITY .space 0x0400 // 0x00B00000->0x80BFFFFF + .space 0x0C00 // PADDING FOR 4KB GRANULARITY .space 0x0400 // 0x00C00000->0x80CFFFFF + .space 0x0C00 // PADDING FOR 4KB GRANULARITY .space 0x0400 // 0x00D00000->0x80DFFFFF + .space 0x0C00 // PADDING FOR 4KB GRANULARITY + =
+.global FlatMapTranslationTable +FlatMapTranslationTable: + .space 0x0400 // 0xYYYYYYYY->0xC00FFFFF + .space 0x0C00 // PADDING FOR 4KB GRANULARITY + .space 0x0400 // 0xYYYYYYYY->0xC01FFFFF + .space 0x0C00 // PADDING FOR 4KB GRANULARITY + .space 0x0400 // 0xYYYYYYYY->0xC02FFFFF + .space 0x0C00 // PADDING FOR 4KB GRANULARITY + .space 0x0400 // 0xYYYYYYYY->0xC03FFFFF + .space 0x0C00 // PADDING FOR 4KB GRANULARITY + .space 0x0400 // 0xYYYYYYYY->0xC04FFFFF + .space 0x0C00 // PADDING FOR 4KB GRANULARITY + .space 0x0400 // 0xYYYYYYYY->0xC05FFFFF + .space 0x0C00 // PADDING FOR 4KB GRANULARITY + .space 0x0400 // 0xYYYYYYYY->0xC06FFFFF + .space 0x0C00 // PADDING FOR 4KB GRANULARITY + .space 0x0400 // 0xYYYYYYYY->0xC07FFFFF + .space 0x0C00 // PADDING FOR 4KB GRANULARITY + .space 0x0400 // 0xYYYYYYYY->0xC08FFFFF + .space 0x0C00 // PADDING FOR 4KB GRANULARITY + .space 0x0400 // 0xYYYYYYYY->0xC09FFFFF + .space 0x0C00 // PADDING FOR 4KB GRANULARITY + .space 0x0400 // 0xYYYYYYYY->0xC0AFFFFF + .space 0x0C00 // PADDING FOR 4KB GRANULARITY + .space 0x0400 // 0xYYYYYYYY->0xC0BFFFFF + .space 0x0C00 // PADDING FOR 4KB GRANULARITY + .space 0x0400 // 0xYYYYYYYY->0xC0CFFFFF + .space 0x0C00 // PADDING FOR 4KB GRANULARITY + .space 0x0400 // 0xYYYYYYYY->0xC0DFFFFF + .space 0x0C00 // PADDING FOR 4KB GRANULARITY + .space 0x0400 // 0xYYYYYYYY->0xC0EFFFFF + .space 0x0C00 // PADDING FOR 4KB GRANULARITY + .space 0x0400 // 0xYYYYYYYY->0xC0FFFFFF + .space 0x0C00 // PADDING FOR 4KB GRANULARITY + =
+.global MasterTranslationTable +MasterTranslationTable: + .space 0x0400 // 0xYYYYYYYY->0xC10FFFFF + .space 0x0C00 // PADDING FOR 4KB GRANULARITY + +.global HyperSpaceTranslationTable +HyperSpaceTranslationTable: + .space 0x0400 // 0xYYYYYYYY->0xC10FFFFF + .space 0x0C00 // PADDING FOR 4KB GRANULARITY + +.global TranslationTableEnd +TranslationTableEnd:
Modified: trunk/reactos/boot/freeldr/freeldr/arch/arm/loader.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/boot/freeldr/freeldr/= arch/arm/loader.c?rev=3D32640&r1=3D32639&r2=3D32640&view=3Ddiff =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D --- trunk/reactos/boot/freeldr/freeldr/arch/arm/loader.c (original) +++ trunk/reactos/boot/freeldr/freeldr/arch/arm/loader.c Mon Mar 10 12:27:1= 4 2008 @@ -13,7 +13,15 @@ #include <internal/arm/mm.h> #include <internal/arm/intrin_i.h> =
+#define KERNEL_DESCRIPTOR_PAGE(x) (((ULONG_PTR)x &~ KSEG0_BASE) >> PAGE_SH= IFT) + /* GLOBALS ***************************************************************= *****/ + +typedef struct _BIOS_MEMORY_DESCRIPTOR +{ + ULONG BlockBase; + ULONG BlockSize; +} BIOS_MEMORY_DESCRIPTOR, *PBIOS_MEMORY_DESCRIPTOR; =
ULONG PageDirectoryStart, PageDirectoryEnd; PLOADER_PARAMETER_BLOCK ArmLoaderBlock; @@ -24,11 +32,23 @@ CHAR ArmNtBootPath[64]; PNLS_DATA_BLOCK ArmNlsDataBlock; PLOADER_PARAMETER_EXTENSION ArmExtension; +BIOS_MEMORY_DESCRIPTOR ArmBoardMemoryDescriptors[16] =3D {{0}}; +PBIOS_MEMORY_DESCRIPTOR ArmBoardMemoryList =3D ArmBoardMemoryDescriptors; +ULONG NumberDescriptors =3D 0; +MEMORY_DESCRIPTOR MDArray[16] =3D {{0}}; +ULONG ArmSharedHeapSize; +PCHAR ArmSharedHeap; + +extern ADDRESS_RANGE ArmBoardMemoryMap[16]; +extern ULONG ArmBoardMemoryMapRangeCount; extern ARM_TRANSLATION_TABLE ArmTranslationTable; -extern ARM_COARSE_PAGE_TABLE BootTranslationTable, KernelTranslationTable; +extern ARM_COARSE_PAGE_TABLE BootTranslationTable, KernelTranslationTable,= FlatMapTranslationTable, MasterTranslationTable, HyperSpaceTranslationTabl= e; extern ROS_KERNEL_ENTRY_POINT KernelEntryPoint; extern ULONG_PTR KernelBase; -extern ULONG_PTR AnsiData, OemData, UnicodeData, RegistryData; +extern ULONG_PTR AnsiData, OemData, UnicodeData, RegistryData, KernelData,= HalData, DriverData[16]; +extern ULONG RegistrySize, AnsiSize, OemSize, UnicodeSize, KernelSize, Hal= Size, DriverSize[16]; +extern ULONG Drivers; +extern ULONG BootStack, TranslationTableStart, TranslationTableEnd; =
ULONG SizeBits[] =3D { @@ -59,9 +79,614 @@ // // Where to map the serial port // -#define UART_VIRTUAL 0xC0000000 +#define UART_VIRTUAL 0xE0000000 + +#define PTE_BASE 0xC0000000 +#define PDE_BASE 0xC1000000 +#define HYPER_SPACE 0xC1100000 + +// +// Take 0x80812345 and extract: +// PTE_BASE[0x808][0x12] +// +#define MiAddressToPte(x) \ + (PTE_BASE + (((x) >> 20) << 12) + ((((x) >> 12) & 0xFF) << 2)) + +#define MiAddressToPde(x) \ + (PDE_BASE + (((x) >> 20) << 2)) =
/* FUNCTIONS *************************************************************= *****/ + +PVOID +ArmAllocateFromSharedHeap(IN ULONG Size) +{ + PVOID Buffer; + + // + // Allocate from the shared heap + // + Buffer =3D &ArmSharedHeap[ArmSharedHeapSize]; + ArmSharedHeapSize +=3D Size; + return Buffer; +} + +PMEMORY_ALLOCATION_DESCRIPTOR +NTAPI +ArmAllocateMemoryDescriptor(VOID) +{ + // + // Allocate a descriptor from the heap + // + return ArmAllocateFromSharedHeap(sizeof(MEMORY_ALLOCATION_DESCRIPTOR)); +} + +VOID +NTAPI +ArmAddBoardMemoryDescriptor(IN ULONG Address, + IN ULONG Size) +{ + PBIOS_MEMORY_DESCRIPTOR BiosBlock =3D ArmBoardMemoryList; + =
+ // + // Loop board DRAM configuration + // + while (BiosBlock->BlockSize > 0) + { + /* Check if we've found a matching head block */ + if (Address + Size =3D=3D BiosBlock->BlockBase) + { + /* Simply enlarge and rebase it */ + BiosBlock->BlockBase =3D Address; + BiosBlock->BlockSize +=3D Size; + break; + } + =
+ /* Check if we've found a matching tail block */ + if (Address =3D=3D (BiosBlock->BlockBase + BiosBlock->BlockSize)) + { + /* Simply enlarge it */ + BiosBlock->BlockSize +=3D Size; + break; + } + =
+ /* Nothing suitable found, try the next block */ + BiosBlock++; + } + =
+ /* No usable blocks found, found a free block instead */ + if (!BiosBlock->BlockSize) + { + /* Write our data */ + BiosBlock->BlockBase =3D Address; + BiosBlock->BlockSize =3D Size; + =
+ /* Create a new block and mark it as the end of the array */ + BiosBlock++; + BiosBlock->BlockBase =3D BiosBlock->BlockSize =3D 0L; + } +} + +VOID +NTAPI +ArmBuildBoardMemoryMap(VOID) +{ + ULONG BlockBegin, BlockEnd; + ULONG j; + =
+ /* Loop the BIOS Memory Map */ + for (j =3D 0; j < ArmBoardMemoryMapRangeCount; j++) + { + /* Get the start and end addresses */ + BlockBegin =3D ArmBoardMemoryMap[j].BaseAddrLow; + BlockEnd =3D ArmBoardMemoryMap[j].BaseAddrLow + ArmBoardMemoryMap[= j].LengthLow - 1; + =
+ /* Make sure this isn't a > 4GB descriptor */ + if (!ArmBoardMemoryMap[j].BaseAddrHigh) + { + /* Make sure we don't overflow */ + if (BlockEnd < BlockBegin) BlockEnd =3D 0xFFFFFFFF; + =
+ /* Check if this is free memory */ + if (ArmBoardMemoryMap[j].Type =3D=3D 1) + { + /* Add it to our BIOS descriptors */ + ArmAddBoardMemoryDescriptor(BlockBegin, BlockEnd - BlockBe= gin + 1); + } + } + } +} + +NTSTATUS +NTAPI +ArmConfigureArcDescriptor(IN ULONG PageBegin, + IN ULONG PageEnd, + IN TYPE_OF_MEMORY MemoryType) +{ + ULONG i; + ULONG BlockBegin, BlockEnd; + MEMORY_TYPE BlockType; + BOOLEAN Combined =3D FALSE; + =
+ /* If this descriptor seems bogus, just return */ + if (PageEnd <=3D PageBegin) return STATUS_SUCCESS; + =
+ /* Loop every ARC descriptor, trying to find one we can modify */ + for (i =3D 0; i < NumberDescriptors; i++) + { + /* Get its settings */ + BlockBegin =3D MDArray[i].BasePage; + BlockEnd =3D MDArray[i].BasePage + MDArray[i].PageCount; + BlockType =3D MDArray[i].MemoryType; + =
+ /* Check if we can fit inside this block */ + if (BlockBegin < PageBegin) + { + /* Check if we are larger then it */ + if ((BlockEnd > PageBegin) && (BlockEnd <=3D PageEnd)) + { + /* Make it end where we start */ + BlockEnd =3D PageBegin; + } + =
+ /* Check if it ends after we do */ + if (BlockEnd > PageEnd) + { + /* Make sure we can allocate a descriptor */ + if (NumberDescriptors =3D=3D 60) return ENOMEM; + =
+ /* Create a descriptor for whatever memory we're not part = of */ + MDArray[NumberDescriptors].MemoryType =3D BlockType; + MDArray[NumberDescriptors].BasePage =3D PageEnd; + MDArray[NumberDescriptors].PageCount =3D BlockEnd - PageE= nd; + NumberDescriptors++; + =
+ /* The next block ending is now where we begin */ + BlockEnd =3D PageBegin; + } + } + else + { + /* Check if the blog begins inside our range */ + if (BlockBegin < PageEnd) + { + /* Check if it ends before we do */ + if (BlockEnd < PageEnd) + { + /* Then make it disappear */ + BlockEnd =3D BlockBegin; + } + else + { + /* Otherwise make it start where we end */ + BlockBegin =3D PageEnd; + } + } + } + =
+ /* Check if the block matches us, and we haven't tried combining y= et */ + if ((BlockType =3D=3D MemoryType) && !(Combined)) + { + /* Check if it starts where we end */ + if (BlockBegin =3D=3D PageEnd) + { + /* Make it start with us, and combine us */ + BlockBegin =3D PageBegin; + Combined =3D TRUE; + } + else if (BlockEnd =3D=3D PageBegin) + { + /* Otherwise, it ends where we begin, combine its ending */ + BlockEnd =3D PageEnd; + Combined =3D TRUE; + } + } + =
+ /* Check the original block data matches with what we came up with= */ + if ((MDArray[i].BasePage =3D=3D BlockBegin) && + (MDArray[i].PageCount =3D=3D BlockEnd - BlockBegin)) + { + /* Then skip it */ + continue; + } + =
+ /* Otherwise, set our new settings for this block */ + MDArray[i].BasePage =3D BlockBegin; + MDArray[i].PageCount =3D BlockEnd - BlockBegin; + =
+ /* Check if we are killing the block */ + if (BlockBegin =3D=3D BlockEnd) + { + /* Delete this block and restart the loop properly */ + NumberDescriptors--; + if (i < NumberDescriptors) MDArray[i] =3D MDArray[NumberDescri= ptors]; + i--; + } + } + =
+ /* If we got here without combining, we need to allocate a new block */ + if (!(Combined) && (MemoryType < LoaderMaximum)) + { + /* Make sure there's enough descriptors */ + if (NumberDescriptors =3D=3D 60) return ENOMEM; + =
+ /* Allocate a new block with our data */ + MDArray[NumberDescriptors].MemoryType =3D MemoryType; + MDArray[NumberDescriptors].BasePage =3D PageBegin; + MDArray[NumberDescriptors].PageCount =3D PageEnd - PageBegin; + NumberDescriptors++; + } + =
+ /* Changes complete, return success */ + return STATUS_SUCCESS; +} + +NTSTATUS +NTAPI +ArmBuildOsMemoryMap(VOID) +{ + PBIOS_MEMORY_DESCRIPTOR MdBlock; + ULONG BlockStart, BlockEnd, BiasedStart, BiasedEnd, PageStart, PageEnd; + NTSTATUS Status =3D STATUS_SUCCESS; + =
+ /* Loop the BIOS Memory Descriptor List */ + MdBlock =3D ArmBoardMemoryList; + while (MdBlock->BlockSize) + { + /* Get the statrt and end addresses */ + BlockStart =3D MdBlock->BlockBase; + BlockEnd =3D BlockStart + MdBlock->BlockSize - 1; + =
+ /* Align them to page boundaries */ + BiasedStart =3D BlockStart & (PAGE_SIZE - 1); + if (BiasedStart) BlockStart =3D BlockStart + PAGE_SIZE - BiasedSta= rt; + BiasedEnd =3D (BlockEnd + 1) & (ULONG)(PAGE_SIZE - 1); + if (BiasedEnd) BlockEnd -=3D BiasedEnd; + =
+ /* Get the actual page numbers */ + PageStart =3D BlockStart >> PAGE_SHIFT; + PageEnd =3D (BlockEnd + 1) >> PAGE_SHIFT; + + /* Check if we did any alignment */ + if (BiasedStart) + { + /* Mark that region as reserved */ + Status =3D ArmConfigureArcDescriptor(PageStart - 1, + PageStart, + MemorySpecialMemory); + if (Status !=3D STATUS_SUCCESS) break; + } + =
+ /* Check if we did any alignment */ + if (BiasedEnd) + { + /* Mark that region as reserved */ + Status =3D ArmConfigureArcDescriptor(PageEnd - 1, + PageEnd, + MemorySpecialMemory); + if (Status !=3D STATUS_SUCCESS) break; + } + =
+ /* It is, mark the memory a free */ + Status =3D ArmConfigureArcDescriptor(PageStart, + PageEnd, + LoaderFree); + =
+ /* If we failed, break out, otherwise, go to the next BIOS block */ + if (Status !=3D STATUS_SUCCESS) break; + MdBlock++; + } + =
+ /* Return error code */ + return Status; +} + +VOID +NTAPI +ArmInsertMemoryDescriptor(IN PMEMORY_ALLOCATION_DESCRIPTOR NewDescriptor) +{ + PLIST_ENTRY ListHead, PreviousEntry, NextEntry; + PMEMORY_ALLOCATION_DESCRIPTOR Descriptor =3D NULL, NextDescriptor =3D = NULL; + =
+ /* Loop the memory descriptor list */ + ListHead =3D &ArmLoaderBlock->MemoryDescriptorListHead; + PreviousEntry =3D ListHead; + NextEntry =3D ListHead->Flink; + while (NextEntry !=3D ListHead) + { + /* Get the current descriptor and check if it's below ours */ + NextDescriptor =3D CONTAINING_RECORD(NextEntry, + MEMORY_ALLOCATION_DESCRIPTOR, + ListEntry); + if (NewDescriptor->BasePage < NextDescriptor->BasePage) break; + =
+ /* It isn't, save the previous entry and descriptor, and try again= */ + PreviousEntry =3D NextEntry; + Descriptor =3D NextDescriptor; + NextEntry =3D NextEntry->Flink; + } + =
+ /* So we found the right spot to insert. Is this free memory? */ + if (NewDescriptor->MemoryType !=3D LoaderFree) + { + /* It isn't, so insert us before the last descriptor */ + InsertHeadList(PreviousEntry, &NewDescriptor->ListEntry); + } + else + { + /* We're free memory. Check if the entry we found is also free mem= ory */ + if ((PreviousEntry !=3D ListHead) && + ((Descriptor->MemoryType =3D=3D LoaderFree) || + (Descriptor->MemoryType =3D=3D LoaderReserve)) && + ((Descriptor->BasePage + Descriptor->PageCount) =3D=3D + NewDescriptor->BasePage)) + { + /* It's free memory, and we're right after it. Enlarge that bl= ock */ + Descriptor->PageCount +=3D NewDescriptor->PageCount; + NewDescriptor =3D Descriptor; + } + else + { + /* Our range scan't be combined, so just insert us separately = */ + InsertHeadList(PreviousEntry, &NewDescriptor->ListEntry); + } + =
+ /* Check if we merged with an existing free memory block */ + if ((NextEntry !=3D ListHead) && + ((NextDescriptor->MemoryType =3D=3D LoaderFree) || + (NextDescriptor->MemoryType =3D=3D LoaderReserve)) && + ((NewDescriptor->BasePage + NewDescriptor->PageCount) =3D=3D + NextDescriptor->BasePage)) + { + /* Update our own block */ + NewDescriptor->PageCount +=3D NextDescriptor->PageCount; + =
+ /* Remove the next block */ + RemoveEntryList(&NextDescriptor->ListEntry); + } + } +} + +NTSTATUS +NTAPI +ArmBuildMemoryDescriptor(IN PMEMORY_ALLOCATION_DESCRIPTOR MemoryDescriptor, + IN MEMORY_TYPE MemoryType, + IN ULONG BasePage, + IN ULONG PageCount) +{ + PMEMORY_ALLOCATION_DESCRIPTOR Descriptor, NextDescriptor =3D NULL; + LONG Delta; + TYPE_OF_MEMORY CurrentType; + BOOLEAN UseNext; + =
+ /* Check how many pages we'll be consuming */ + Delta =3D BasePage - MemoryDescriptor->BasePage; + if (!(Delta) && (PageCount =3D=3D MemoryDescriptor->PageCount)) + { + /* We can simply convert the current descriptor into our new type = */ + MemoryDescriptor->MemoryType =3D MemoryType; + } + else + { + /* Get the current memory type of the descriptor, and reserve it */ + CurrentType =3D MemoryDescriptor->MemoryType; + MemoryDescriptor->MemoryType =3D LoaderSpecialMemory; + =
+ /* Check if we'll need another descriptor for what's left of memor= y */ + UseNext =3D ((BasePage !=3D MemoryDescriptor->BasePage) && + (Delta + PageCount !=3D MemoryDescriptor->PageCount)); + =
+ /* Get a descriptor */ + Descriptor =3D ArmAllocateMemoryDescriptor(); + if (!Descriptor) return STATUS_INSUFFICIENT_RESOURCES; + =
+ /* Check if we are using another descriptor */ + if (UseNext) + { + /* Allocate that one too */ + NextDescriptor =3D ArmAllocateMemoryDescriptor(); + if (!NextDescriptor) return STATUS_INSUFFICIENT_RESOURCES; + } + =
+ /* Build the descriptor we got */ + Descriptor->MemoryType =3D MemoryType; + Descriptor->BasePage =3D BasePage; + Descriptor->PageCount =3D PageCount; + =
+ /* Check if we're starting at the same place as the old one */ + if (BasePage =3D=3D MemoryDescriptor->BasePage) + { + /* Simply decrease the old descriptor and rebase it */ + MemoryDescriptor->BasePage +=3D PageCount; + MemoryDescriptor->PageCount -=3D PageCount; + MemoryDescriptor->MemoryType =3D CurrentType; + } + else if (Delta + PageCount =3D=3D MemoryDescriptor->PageCount) + { + /* We finish where the old one did, shorten it */ + MemoryDescriptor->PageCount -=3D PageCount; + MemoryDescriptor->MemoryType =3D CurrentType; + } + else + { + /* We're inside the current block, mark our free region */ + NextDescriptor->MemoryType =3D LoaderFree; + NextDescriptor->BasePage =3D BasePage + PageCount; + NextDescriptor->PageCount =3D MemoryDescriptor->PageCount - + (PageCount + Delta); + =
+ /* And cut down the current descriptor */ + MemoryDescriptor->PageCount =3D Delta; + MemoryDescriptor->MemoryType =3D CurrentType; + =
+ /* Finally, insert our new free descriptor into the list */ + ArmInsertMemoryDescriptor(NextDescriptor); + } + =
+ /* Insert the descriptor we allocated */ + ArmInsertMemoryDescriptor(Descriptor); + } + =
+ /* Return success */ + return STATUS_SUCCESS; +} + +PMEMORY_ALLOCATION_DESCRIPTOR +NTAPI +ArmFindMemoryDescriptor(IN ULONG BasePage) +{ + PMEMORY_ALLOCATION_DESCRIPTOR MdBlock =3D NULL; + PLIST_ENTRY NextEntry, ListHead; + =
+ /* Scan the memory descriptor list */ + ListHead =3D &ArmLoaderBlock->MemoryDescriptorListHead; + NextEntry =3D ListHead->Flink; + while (NextEntry !=3D ListHead) + { + /* Get the current descriptor */ + MdBlock =3D CONTAINING_RECORD(NextEntry, + MEMORY_ALLOCATION_DESCRIPTOR, + ListEntry); + + /* Check if it can contain our memory range */ + if ((MdBlock->BasePage <=3D BasePage) && + (MdBlock->BasePage + MdBlock->PageCount > BasePage)) + { + /* It can, break out */ + break; + } + =
+ /* Go to the next descriptor */ + NextEntry =3D NextEntry->Flink; + } + =
+ /* Return the descriptor we found, if any */ + return MdBlock; +} + +NTSTATUS +NTAPI +ArmCreateMemoryDescriptor(IN TYPE_OF_MEMORY MemoryType, + IN ULONG BasePage, + IN ULONG PageCount, + IN ULONG Alignment, + OUT PULONG ReturnedBase) +{ + PMEMORY_ALLOCATION_DESCRIPTOR MdBlock; + ULONG AlignedBase, AlignedLimit; + PMEMORY_ALLOCATION_DESCRIPTOR ActiveMdBlock; + ULONG ActiveAlignedBase =3D 0; + PLIST_ENTRY NextEntry, ListHead; + =
+ /* If no information was given, make some assumptions */ + if (!Alignment) Alignment =3D 1; + if (!PageCount) PageCount =3D 1; + =
+ /* Start looking for a matching descvriptor */ + do + { + /* Calculate the limit of the range */ + AlignedLimit =3D PageCount + BasePage; + =
+ /* Find a descriptor that already contains our base address */ + MdBlock =3D ArmFindMemoryDescriptor(BasePage); + if (MdBlock) + { + /* If it contains our limit as well, break out early */ + if ((MdBlock->PageCount + MdBlock->BasePage) >=3D AlignedLimit= ) break; + } + =
+ /* Loop the memory list */ + AlignedBase =3D 0; + ActiveMdBlock =3D NULL; + ListHead =3D &ArmLoaderBlock->MemoryDescriptorListHead; + NextEntry =3D ListHead->Flink; + while (NextEntry !=3D ListHead) + { + /* Get the current descriptors */ + MdBlock =3D CONTAINING_RECORD(NextEntry, + MEMORY_ALLOCATION_DESCRIPTOR, + ListEntry); + =
+ /* Align the base address and our limit */ + AlignedBase =3D (MdBlock->BasePage + (Alignment - 1)) &~ Align= ment; + AlignedLimit =3D MdBlock->PageCount - + AlignedBase + + MdBlock->BasePage; + =
+ /* Check if this is a free block that can satisfy us */ + if ((MdBlock->MemoryType =3D=3D LoaderFree) && + (AlignedLimit <=3D MdBlock->PageCount) && + (PageCount <=3D AlignedLimit)) + { + /* It is, stop searching */ + ActiveMdBlock =3D MdBlock; + ActiveAlignedBase =3D AlignedBase; + break; + } + =
+ /* Try the next block */ + NextEntry =3D NextEntry->Flink; + } + =
+ /* See if we came up with an adequate block */ + if (ActiveMdBlock) + { + /* Generate a descriptor in it */ + *ReturnedBase =3D AlignedBase; + return ArmBuildMemoryDescriptor(ActiveMdBlock, + MemoryType, + ActiveAlignedBase, + PageCount); + } + } while (TRUE); + =
+ /* We found a matching block, generate a descriptor with it */ + *ReturnedBase =3D BasePage; + return ArmBuildMemoryDescriptor(MdBlock, MemoryType, BasePage, PageCou= nt); +} + +NTSTATUS +NTAPI +ArmBuildLoaderMemoryList(VOID) +{ + PMEMORY_ALLOCATION_DESCRIPTOR Descriptor; + MEMORY_DESCRIPTOR *Memory; + ULONG i; + =
+ /* Loop all BIOS Memory Descriptors */ + for (i =3D 0; i < NumberDescriptors; i++) + { + /* Get the current descriptor */ + Memory =3D &MDArray[i]; + =
+ /* Allocate an NT Memory Descriptor */ + Descriptor =3D ArmAllocateMemoryDescriptor(); + if (!Descriptor) return ENOMEM; + =
+ /* Copy the memory type */ + Descriptor->MemoryType =3D Memory->MemoryType; + if (Memory->MemoryType =3D=3D MemoryFreeContiguous) + { + /* Convert this to free */ + Descriptor->MemoryType =3D LoaderFree; + } + else if (Memory->MemoryType =3D=3D MemorySpecialMemory) + { + /* Convert this to special memory */ + Descriptor->MemoryType =3D LoaderSpecialMemory; + } + =
+ /* Copy the range data */ + Descriptor->BasePage =3D Memory->BasePage; + Descriptor->PageCount =3D Memory->PageCount; + =
+ /* Insert the descriptor */ + if (Descriptor->PageCount) ArmInsertMemoryDescriptor(Descriptor); + } + =
+ /* All went well */ + return STATUS_SUCCESS; +} =
VOID ArmSetupPageDirectory(VOID) @@ -70,20 +695,23 @@ ARM_DOMAIN_REGISTER DomainRegister; ARM_PTE Pte; ULONG i, j; - PARM_TRANSLATION_TABLE MasterTable; - PARM_COARSE_PAGE_TABLE BootTable, KernelTable; + PARM_TRANSLATION_TABLE ArmTable; + PARM_COARSE_PAGE_TABLE BootTable, KernelTable, FlatMapTable, MasterTab= le, HyperSpaceTable; =
// // Get the PDEs that we will use // - MasterTable =3D &ArmTranslationTable; + ArmTable =3D &ArmTranslationTable; BootTable =3D &BootTranslationTable; KernelTable =3D &KernelTranslationTable; + FlatMapTable =3D &FlatMapTranslationTable; + MasterTable =3D &MasterTranslationTable; + HyperSpaceTable =3D &HyperSpaceTranslationTable; =
// // Set the master L1 PDE as the TTB // - TtbRegister.AsUlong =3D (ULONG)MasterTable; + TtbRegister.AsUlong =3D (ULONG)ArmTable; ASSERT(TtbRegister.Reserved =3D=3D 0); KeArmTranslationTableRegisterSet(TtbRegister); =
@@ -97,7 +725,7 @@ // // Set Fault PTEs everywhere // - RtlZeroMemory(MasterTable, sizeof(ARM_TRANSLATION_TABLE)); + RtlZeroMemory(ArmTable, sizeof(ARM_TRANSLATION_TABLE)); =
// // Identity map the first MB of memory @@ -110,22 +738,102 @@ Pte.L1.Section.Access =3D SupervisorAccess; Pte.L1.Section.BaseAddress =3D 0; Pte.L1.Section.Ignored =3D Pte.L1.Section.Ignored1 =3D 0; - MasterTable->Pte[0] =3D Pte; - + ArmTable->Pte[0] =3D Pte; + =
// // Map the page in MMIO space that contains the serial port into virtu= al memory // Pte.L1.Section.BaseAddress =3D ArmBoardBlock->UartRegisterBase >> PDE_= SHIFT; - MasterTable->Pte[UART_VIRTUAL >> PDE_SHIFT] =3D Pte; - - // - // Create template PTE for the coarse page tables which map the first = 8MB + ArmTable->Pte[UART_VIRTUAL >> PDE_SHIFT] =3D Pte; + + // + // Create template PTE for the coarse page table which maps the PTE_BA= SE // Pte.L1.Coarse.Type =3D CoarsePte; Pte.L1.Coarse.Domain =3D Domain0; Pte.L1.Coarse.Reserved =3D 1; // ARM926EJ-S manual recommends setting = to 1 + Pte.L1.Coarse.Ignored =3D Pte.L1.Coarse.Ignored1 =3D 0; + Pte.L1.Coarse.BaseAddress =3D (ULONG)FlatMapTable >> CPT_SHIFT; + + // + // On x86, there is 4MB of space, starting at 0xC0000000 to 0xC0400000 + // which contains the mappings for each PTE on the system. 4MB is need= ed + // since for 4GB, there will be 1 million PTEs, each of 4KB. + // + // To describe a 4MB region, on x86, only requires a page table, which= can + // be linked from the page table directory. + // + // On the other hand, on ARM, we can only describe 1MB regions, so we = need + // four times less PTE entries to represent a single mapping (an L2 co= arse + // page table). This is problematic, because this would only take up 1= KB of + // space, and we can't have a page that small. + // + // This means we must: + // + // - Allocate page tables (in physical memory) with 4KB granularity, i= nstead + // of 1KB (the other 3KB is unused and invalid). + // + // - "Skip" the other 3KB in the region, because we can't point to ano= ther + // coarse page table after just 1KB. + // + // So 0xC0000000 will be mapped to the page table that maps the range = of + // 0x00000000 to 0x01000000, while 0xC0001000 till be mapped to the pa= ge + // table that maps the area from 0x01000000 to 0x02000000, and so on. = In + // total, this will require 4 million entries, and additionally, becau= se of + // the padding, since each 256 entries will be 4KB (instead of 1KB), t= his + // means we'll need 16MB (0xC0000000 to 0xC1000000). + // + // We call this region the flat-map area + // + for (i =3D (PTE_BASE >> PDE_SHIFT); i < ((PTE_BASE + 0x1000000) >> PDE= _SHIFT); i++) + { + // + // Write PTE and update the base address (next MB) for the next one + // + ArmTable->Pte[i] =3D Pte; + Pte.L1.Coarse.BaseAddress +=3D 4; + } + =
+ // + // On x86, there is also the region of 0xC0300000 to 0xC03080000 which= maps + // to the various PDEs on the system. Yes, this overlaps with the abov= e, and + // works because of an insidious dark magic (self-mapping the PDE as a= PTE). + // Unfortunately, this doesn't work on ARM, firstly because the size o= f a L1 + // page table is different than from an L2 page table, and secondly, w= hich + // is even worse, the format for an L1 page table is different than th= e one + // for an L2 page table -- basically meaning we cannot self-map. + // + // However, we somewhat emulate this behavior on ARM. This will be exp= ensive + // since we manually need to keep track of every page directory added = and + // add an entry in our flat-map region. We also need to keep track of = every + // change in the TTB, so that we can update the mappings in our PDE re= gion. + // + // Note that for us, this region starts at 0xC1000000, after the flat-= map + // area. + // + // Finally, to deal with different sizes (1KB page tables, 4KB page si= ze!), + // we pad the ARM L2 page tables to make them 4KB, so that each page w= ill + // therefore point to an L2 page table. + // + // This region is a lot easier than the first -- an L1 page table is o= nly + // 16KB, so to access any index inside it, we just need 4 pages, since= each + // page is 4KB... Clearly, there's also no need to pad in this case. + // + // We'll call this region the master translation area. + // + Pte.L1.Coarse.BaseAddress =3D (ULONG)MasterTable >> CPT_SHIFT; + ArmTable->Pte[PDE_BASE >> PDE_SHIFT] =3D Pte; + =
+ // + // Now create the template for the hyperspace table which maps 1MB + // + Pte.L1.Coarse.BaseAddress =3D (ULONG)HyperSpaceTable >> CPT_SHIFT; + ArmTable->Pte[HYPER_SPACE >> PDE_SHIFT] =3D Pte; + + // + // Now create the template for the coarse page tables which map the fi= rst 8MB + // Pte.L1.Coarse.BaseAddress =3D (ULONG)BootTable >> CPT_SHIFT; - Pte.L1.Coarse.Ignored =3D Pte.L1.Coarse.Ignored1 =3D 0; =
// // Map 0x00000000 - 0x007FFFFF to 0x80000000 - 0x807FFFFF. @@ -136,8 +844,8 @@ // // Write PTE and update the base address (next MB) for the next one // - MasterTable->Pte[i] =3D Pte; - Pte.L1.Coarse.BaseAddress++; + ArmTable->Pte[i] =3D Pte; + Pte.L1.Coarse.BaseAddress +=3D 4; } =
// @@ -156,8 +864,8 @@ // // Write PTE and update the base address (next MB) for the next one // - MasterTable->Pte[i] =3D Pte; - Pte.L1.Coarse.BaseAddress++; + ArmTable->Pte[i] =3D Pte; + Pte.L1.Coarse.BaseAddress +=3D 4; } =
// @@ -225,6 +933,88 @@ // KernelTable++; } + + // + // Now we need to create the PTEs for the addresses which have been ma= pped + // already. + // + // We have allocated 4 page table directories: + // + // - One for the kernel, 6MB + // - One for low-memory FreeLDR, 8MB + // - One for identity-mapping below 1MB, 1MB + // - And finally, one for the flat-map itself, 16MB + // =
+ // - Each MB mapped is a 1KB table, which we'll use a page to referenc= e, so + // we will require 31 pages. + // + =
+ // + // For the 0x80000000 region (8MB) + // + Pte.L2.Small.BaseAddress =3D (ULONG)&BootTranslationTable >> PTE_SHIFT; + FlatMapTable =3D &(&FlatMapTranslationTable)[0x80000000 >> 28]; + for (i =3D 0; i < 8; i++) + { + // + // Point to the page table mapping the next MB + // + FlatMapTable->Pte[i] =3D Pte; + Pte.L2.Small.BaseAddress++; =
+ } + =
+ // + // For the 0x80800000 region (6MB) + // + Pte.L2.Small.BaseAddress =3D (ULONG)&KernelTranslationTable >> PTE_SHI= FT; + for (i =3D 8; i < 14; i++) + { + // + // Point to the page table mapping the next MB + // + FlatMapTable->Pte[i] =3D Pte; + Pte.L2.Small.BaseAddress++; =
+ } + =
+ // + // For the 0xC0000000 region (16MB) + // + Pte.L2.Small.BaseAddress =3D (ULONG)&FlatMapTranslationTable >> PTE_SH= IFT; + FlatMapTable =3D &(&FlatMapTranslationTable)[0xC0000000 >> 28]; + for (i =3D 0; i < 16; i++) + { + // + // Point to the page table mapping the next MB + // + FlatMapTable->Pte[i] =3D Pte; + Pte.L2.Small.BaseAddress++; =
+ } + =
+ // + // For the 0xC1000000 region (1MB) + // + Pte.L2.Small.BaseAddress =3D (ULONG)&MasterTranslationTable >> PTE_SHI= FT; + FlatMapTable->Pte[16] =3D Pte; + =
+ // + // And finally for the 0xC1100000 region (1MB) + // + Pte.L2.Small.BaseAddress =3D (ULONG)&HyperSpaceTranslationTable >> PTE= _SHIFT; + FlatMapTable->Pte[17] =3D Pte; + + // + // Now we handle the master translation area for our PDEs. We'll just = make + // the 4 page tables point to the ARM TTB. + // + Pte.L2.Small.BaseAddress =3D (ULONG)&ArmTranslationTable >> PTE_SHIFT; + for (i =3D 0; i < 4; i++) + { + // + // Point to the page table mapping the next MB + // + MasterTable->Pte[i] =3D Pte; + Pte.L2.Small.BaseAddress++; =
+ } } =
VOID @@ -259,17 +1049,25 @@ ArmPrepareForReactOS(IN BOOLEAN Setup) { =
ARM_CACHE_REGISTER CacheReg; - PVOID Base; + PVOID Base, MemBase; PCHAR BootPath, HalPath; + NTSTATUS Status; + ULONG Dummy, i; + PLDR_DATA_TABLE_ENTRY LdrEntry; + =
+ // + // Allocate the ARM Shared Heap + // + ArmSharedHeap =3D MmAllocateMemory(PAGE_SIZE); + ArmSharedHeapSize =3D 0; + if (!ArmSharedHeap) return; =
// // Allocate the loader block and extension // - ArmLoaderBlock =3D MmAllocateMemoryWithType(sizeof(LOADER_PARAMETER_BL= OCK), - LoaderOsloaderHeap); + ArmLoaderBlock =3D ArmAllocateFromSharedHeap(sizeof(LOADER_PARAMETER_B= LOCK)); if (!ArmLoaderBlock) return; - ArmExtension =3D MmAllocateMemoryWithType(sizeof(LOADER_PARAMETER_EXTE= NSION), - LoaderOsloaderHeap); + ArmExtension =3D ArmAllocateFromSharedHeap(sizeof(LOADER_PARAMETER_EXT= ENSION)); if (!ArmExtension) return; =
// @@ -286,8 +1084,78 @@ ArmLoaderBlock->SetupLdrBlock =3D NULL; =
// - // TODO: Setup memory descriptors - // + // Add the Board Memory Map from U-Boot into the STARTUP.COM-style =
+ // BIOS descriptor format -- this needs to be removed later. + // + ArmBuildBoardMemoryMap(); + =
+ // + // Now basically convert these entries to the ARC format, so that we c= an + // get a good map of free (usable) memory + // + ArmBuildOsMemoryMap(); + + // + // NT uses an extended ARC format, with slightly different memory type= s. + // We also want to link the ARC descriptors together into a linked lis= t, + // instead of the array, and allocate the semi-permanent storage in wh= ich + // these entries will be stored so that the kernel can read them. + // + ArmBuildLoaderMemoryList(); + =
+ // + // Setup descriptor for the shared heap + // + Status =3D ArmCreateMemoryDescriptor(LoaderOsloaderHeap, + (ULONG_PTR)ArmSharedHeap >> PAGE_SH= IFT, + ADDRESS_AND_SIZE_TO_SPAN_PAGES(ArmS= haredHeap, + ArmS= haredHeapSize), + 0, + &Dummy); + if (Status !=3D STATUS_SUCCESS) return; + + // + // Setup descriptor for the boot stack + // + Status =3D ArmCreateMemoryDescriptor(LoaderOsloaderStack, + (ULONG_PTR)&BootStack >> PAGE_SHIFT, + 4, + 0, + &Dummy); + if (Status !=3D STATUS_SUCCESS) return; + + // + // Setup descriptor for the boot page tables + // + Status =3D ArmCreateMemoryDescriptor(LoaderMemoryData, + (ULONG_PTR)&TranslationTableStart >=
PAGE_SHIFT,
+ ((ULONG_PTR)&TranslationTableEnd - + (ULONG_PTR)&TranslationTableStart)= / PAGE_SIZE, + 0, + &Dummy); + if (Status !=3D STATUS_SUCCESS) return; + + // + // Setup descriptor for the kernel + // + Status =3D ArmCreateMemoryDescriptor(LoaderSystemCode, + KernelData >> PAGE_SHIFT, + ADDRESS_AND_SIZE_TO_SPAN_PAGES(Kern= elData, + Kern= elSize), + 0, + &Dummy); + if (Status !=3D STATUS_SUCCESS) return; + =
+ // + // Setup descriptor for the HAL + // + Status =3D ArmCreateMemoryDescriptor(LoaderHalCode, + HalData >> PAGE_SHIFT, + ADDRESS_AND_SIZE_TO_SPAN_PAGES(HalD= ata, + HalS= ize), + 0, + &Dummy); + if (Status !=3D STATUS_SUCCESS) return; =
// // Setup registry data @@ -295,14 +1163,24 @@ ArmLoaderBlock->RegistryBase =3D (PVOID)((ULONG_PTR)RegistryData | KSE= G0_BASE); =
// + // Create an MD for it + // + Status =3D ArmCreateMemoryDescriptor(LoaderRegistryData, + RegistryData >> PAGE_SHIFT, + ADDRESS_AND_SIZE_TO_SPAN_PAGES(Regi= stryData, + Regi= strySize), + 0, + &Dummy); + if (Status !=3D STATUS_SUCCESS) return; + =
+ // // TODO: Setup ARC Hardware tree data // =
// // Setup NLS data // - ArmNlsDataBlock =3D MmAllocateMemoryWithType(sizeof(NLS_DATA_BLOCK), - LoaderOsloaderHeap); + ArmNlsDataBlock =3D ArmAllocateFromSharedHeap(sizeof(NLS_DATA_BLOCK)); ArmLoaderBlock->NlsData =3D ArmNlsDataBlock; ArmLoaderBlock->NlsData->AnsiCodePageData =3D (PVOID)(AnsiData | KSEG0= _BASE); ArmLoaderBlock->NlsData->OemCodePageData =3D (PVOID)(OemData | KSEG0_B= ASE); @@ -310,8 +1188,70 @@ ArmLoaderBlock->NlsData =3D (PVOID)((ULONG_PTR)ArmLoaderBlock->NlsData= | KSEG0_BASE); =
// + // Setup ANSI NLS Memory Descriptor + // + Status =3D ArmCreateMemoryDescriptor(LoaderNlsData, + AnsiData >> PAGE_SHIFT, + ADDRESS_AND_SIZE_TO_SPAN_PAGES(Ansi= Data, + Ansi= Size), + 0, + &Dummy); + if (Status !=3D STATUS_SUCCESS) return; + =
+ // + // Setup OEM NLS Memory Descriptor + // + Status =3D ArmCreateMemoryDescriptor(LoaderNlsData, + OemData >> PAGE_SHIFT, + ADDRESS_AND_SIZE_TO_SPAN_PAGES(OemD= ata, + OemS= ize), + 0, + &Dummy); + if (Status !=3D STATUS_SUCCESS) return; + =
+ // + // Setup Unicode NLS Memory Descriptor + // + Status =3D ArmCreateMemoryDescriptor(LoaderNlsData, + UnicodeData >> PAGE_SHIFT, + ADDRESS_AND_SIZE_TO_SPAN_PAGES(Unic= odeData, + Unic= odeSize), + 0, + &Dummy); + if (Status !=3D STATUS_SUCCESS) return; + =
+ // + // Setup loader entry for the kernel + // + LdrEntry =3D ArmAllocateFromSharedHeap(sizeof(LDR_DATA_TABLE_ENTRY)); + RtlZeroMemory(LdrEntry, sizeof(LDR_DATA_TABLE_ENTRY)); + LdrEntry->DllBase =3D (PVOID)KernelBase; + LdrEntry->SizeOfImage =3D KernelSize; + LdrEntry->EntryPoint =3D KernelEntryPoint; + LdrEntry->LoadCount =3D 1; + LdrEntry->Flags =3D LDRP_IMAGE_DLL | LDRP_ENTRY_PROCESSED; + InsertTailList(&ArmLoaderBlock->LoadOrderListHead, &LdrEntry->InLoadOr= derLinks); + =
+ // // TODO: Setup boot-driver data // + =
+ // + // Build descriptors for the drivers loaded + // + for (i =3D 0; i < Drivers; i++) + { + // + // Build a descriptor for the driver + // + Status =3D ArmCreateMemoryDescriptor(LoaderBootDriver, + DriverData[i] >> PAGE_SHIFT, + ADDRESS_AND_SIZE_TO_SPAN_PAGES(= DriverData[i], + = DriverSize[i]), + 0, + &Dummy); + if (Status !=3D STATUS_SUCCESS) return; + } =
// // Setup extension parameters @@ -377,7 +1317,7 @@ ArmLoaderBlock->u.Arm.SecondLevelDcacheFillSize =3D ArmLoaderBlock->u.Arm.SecondLevelIcacheSize =3D ArmLoaderBlock->u.Arm.SecondLevelIcacheFillSize =3D 0; - + =
// // Allocate the Interrupt stack // @@ -386,6 +1326,16 @@ ArmLoaderBlock->u.Arm.InterruptStack +=3D KERNEL_STACK_SIZE; =
// + // Build an entry for it + // + Status =3D ArmCreateMemoryDescriptor(LoaderStartupDpcStack, + (ULONG_PTR)Base >> PAGE_SHIFT, + KERNEL_STACK_SIZE / PAGE_SIZE, + 0, + &Dummy); + if (Status !=3D STATUS_SUCCESS) return; + =
+ // // Allocate the Kernel Boot stack // Base =3D MmAllocateMemoryWithType(KERNEL_STACK_SIZE, LoaderStartupKern= elStack); @@ -393,26 +1343,68 @@ ArmLoaderBlock->KernelStack +=3D KERNEL_STACK_SIZE; =
// + // Build an entry for it + // + Status =3D ArmCreateMemoryDescriptor(LoaderStartupKernelStack, + (ULONG_PTR)Base >> PAGE_SHIFT, + KERNEL_STACK_SIZE / PAGE_SIZE, + 0, + &Dummy); + if (Status !=3D STATUS_SUCCESS) return; + + // // Allocate the Abort stack // Base =3D MmAllocateMemoryWithType(KERNEL_STACK_SIZE, LoaderStartupPani= cStack); ArmLoaderBlock->u.Arm.PanicStack =3D KSEG0_BASE | (ULONG)Base; ArmLoaderBlock->u.Arm.PanicStack +=3D KERNEL_STACK_SIZE; - - // - // Allocate the PCR page -- align it to 1MB (we only need 4KB) + =
+ // + // Build an entry for it + // + Status =3D ArmCreateMemoryDescriptor(LoaderStartupPanicStack, + (ULONG_PTR)Base >> PAGE_SHIFT, + KERNEL_STACK_SIZE / PAGE_SIZE, + 0, + &Dummy); + if (Status !=3D STATUS_SUCCESS) return; + + // + // Allocate the PCR/KUSER_SHARED page -- align it to 1MB (we only need= 2x4KB) // Base =3D MmAllocateMemoryWithType(2 * 1024 * 1024, LoaderStartupPcrPag= e); + MemBase =3D Base; Base =3D (PVOID)ROUND_UP(Base, 1 * 1024 * 1024); ArmLoaderBlock->u.Arm.PcrPage =3D (ULONG)Base >> PDE_SHIFT; - - // - // Allocate PDR pages -- align them to 1MB (we only need 3xKB) + =
+ // + // Build an entry for the KPCR and KUSER_SHARED_DATA + // + Status =3D ArmCreateMemoryDescriptor(LoaderStartupPcrPage, + (ULONG_PTR)MemBase >> PAGE_SHIFT, + (2 * 1024 * 1024) / PAGE_SIZE, + 0, + &Dummy); + if (Status !=3D STATUS_SUCCESS) return; + =
+ // + // Allocate PDR pages -- align them to 1MB (we only need 3x4KB) // Base =3D MmAllocateMemoryWithType(4 * 1024 * 1024, LoaderStartupPdrPag= e); + MemBase =3D Base; Base =3D (PVOID)ROUND_UP(Base, 1 * 1024 * 1024); ArmLoaderBlock->u.Arm.PdrPage =3D (ULONG)Base >> PDE_SHIFT; - =
+ + // + // Build an entry for the PDR, PRCB and initial KPROCESS/KTHREAD + // + Status =3D ArmCreateMemoryDescriptor(LoaderStartupPdrPage, + (ULONG_PTR)MemBase >> PAGE_SHIFT, + (4 * 1024 * 1024) / PAGE_SIZE, + 0, + &Dummy); + if (Status !=3D STATUS_SUCCESS) return; + // // Set initial PRCB, Thread and Process on the last PDR page //
Modified: trunk/reactos/boot/freeldr/freeldr/arch/arm/macharm.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/boot/freeldr/freeldr/= arch/arm/macharm.c?rev=3D32640&r1=3D32639&r2=3D32640&view=3Ddiff =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D --- trunk/reactos/boot/freeldr/freeldr/arch/arm/macharm.c (original) +++ trunk/reactos/boot/freeldr/freeldr/arch/arm/macharm.c Mon Mar 10 12:27:= 14 2008 @@ -15,12 +15,16 @@ PARM_BOARD_CONFIGURATION_BLOCK ArmBoardBlock; ULONG BootDrive, BootPartition; VOID ArmPrepareForReactOS(IN BOOLEAN Setup); +ADDRESS_RANGE ArmBoardMemoryMap[16]; +ULONG ArmBoardMemoryMapRangeCount; =
/* FUNCTIONS *************************************************************= *****/ =
VOID ArmInit(IN PARM_BOARD_CONFIGURATION_BLOCK BootContext) { + ULONG i; + // // Remember the pointer // @@ -37,6 +41,22 @@ // ASSERT((ArmBoardBlock->BoardType =3D=3D MACH_TYPE_FEROCEON) || (ArmBoardBlock->BoardType =3D=3D MACH_TYPE_VERSATILE_PB)); + + // + // Save data required for memory initialization + // + ArmBoardMemoryMapRangeCount =3D ArmBoardBlock->MemoryMapEntryCount; + ASSERT(ArmBoardMemoryMapRangeCount !=3D 0); + ASSERT(ArmBoardMemoryMapRangeCount < 16); + for (i =3D 0; i < ArmBoardMemoryMapRangeCount; i++) + { + // + // Copy each entry + // + RtlCopyMemory(&ArmBoardMemoryMap[i], + &ArmBoardBlock->MemoryMap[i], + sizeof(ADDRESS_RANGE)); + } =
// // Call FreeLDR's portable entrypoint with our command-line
Modified: trunk/reactos/boot/freeldr/freeldr/reactos/imageldr.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/boot/freeldr/freeldr/= reactos/imageldr.c?rev=3D32640&r1=3D32639&r2=3D32640&view=3Ddiff =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D --- trunk/reactos/boot/freeldr/freeldr/reactos/imageldr.c (original) +++ trunk/reactos/boot/freeldr/freeldr/reactos/imageldr.c Mon Mar 10 12:27:= 14 2008 @@ -16,7 +16,10 @@ ); =
extern BOOLEAN FrLdrLoadDriver(PCHAR szFileName, INT nPos); -PVOID AnsiData, OemData, UnicodeData, RegistryData; +ULONG Drivers; +PVOID AnsiData, OemData, UnicodeData, RegistryData, KernelData, HalData, D= riverData[16]; +ULONG RegistrySize, AnsiSize, OemSize, UnicodeSize, KernelSize, HalSize, D= riverSize[16]; + /* MODULE MANAGEMENT *****************************************************= *****/ =
PLOADER_MODULE @@ -101,19 +104,23 @@ if (!_stricmp(NameBuffer, "ansi.nls")) { AnsiData =3D (PVOID)NextModuleBase; + AnsiSize =3D LocalModuleSize; } else if (!_stricmp(NameBuffer, "oem.nls")) { OemData =3D (PVOID)NextModuleBase; + OemSize =3D LocalModuleSize; } else if (!_stricmp(NameBuffer, "casemap.nls")) { UnicodeData =3D (PVOID)NextModuleBase; + UnicodeSize =3D LocalModuleSize; } else if (!(_stricmp(NameBuffer, "system")) || !(_stricmp(NameBuffer, "system.hiv"))) { RegistryData =3D (PVOID)NextModuleBase; + RegistrySize =3D LocalModuleSize; } =
/* Load the file image */ @@ -548,6 +555,24 @@ reactos_modules[ImageId].String =3D (ULONG_PTR)reactos_module_strings[= ImageId]; LoaderBlock.ModsCount++; =
+ /* Detect kernel or HAL */ + if (!_stricmp(Name, "ntoskrnl.exe")) + { + KernelData =3D (PVOID)NextModuleBase; + KernelSize =3D ImageSize; + } + else if (!_stricmp(Name, "hal.dll")) + { + HalData =3D (PVOID)NextModuleBase; + HalSize =3D ImageSize; + } + else + { + DriverData[Drivers] =3D (PVOID)NextModuleBase; + DriverSize[Drivers] =3D ImageSize; + Drivers++; + } + =
/* Increase the next Load Base */ NextModuleBase =3D ROUND_UP(NextModuleBase + ImageSize, PAGE_SIZE); =
Modified: trunk/reactos/include/ndk/arm/mmtypes.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/include/ndk/arm/mmtyp= es.h?rev=3D32640&r1=3D32639&r2=3D32640&view=3Ddiff =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D --- trunk/reactos/include/ndk/arm/mmtypes.h (original) +++ trunk/reactos/include/ndk/arm/mmtypes.h Mon Mar 10 12:27:14 2008 @@ -47,19 +47,87 @@ // typedef struct _HARDWARE_PTE_ARM { - ULONG Valid:1; - ULONG Write:1; - ULONG Owner:1; - ULONG WriteThrough:1; - ULONG CacheDisable:1; - ULONG Accessed:1; - ULONG Dirty:1; - ULONG LargePage:1; - ULONG Global:1; - ULONG CopyOnWrite:1; - ULONG Prototype: 1; - ULONG reserved: 1; - ULONG PageFrameNumber:20; + union + { + union + { + struct + { + ULONG Type:2; + ULONG Unused:30; + } Fault; + struct + { + ULONG Type:2; + ULONG Ignored:2; + ULONG Reserved:1; + ULONG Domain:4; + ULONG Ignored1:1; + ULONG BaseAddress:22; + } Coarse; + struct + { + ULONG Type:2; + ULONG Buffered:1; + ULONG Cached:1; + ULONG Reserved:1; + ULONG Domain:4; + ULONG Ignored:1; + ULONG Access:2; + ULONG Ignored1:8; + ULONG BaseAddress:12; + } Section; + struct + { + ULONG Type:2; + ULONG Reserved:3; + ULONG Domain:4; + ULONG Ignored:3; + ULONG BaseAddress:20; + } Fine; + } L1; + union + { + struct + { + ULONG Type:2; + ULONG Unused:30; + } Fault; + struct + { + ULONG Type:2; + ULONG Buffered:1; + ULONG Cached:1; + ULONG Access0:2; + ULONG Access1:2; + ULONG Access2:2; + ULONG Access3:2; + ULONG Ignored:4; + ULONG BaseAddress:16; + } Large; + struct + { + ULONG Type:2; + ULONG Buffered:1; + ULONG Cached:1; + ULONG Access0:2; + ULONG Access1:2; + ULONG Access2:2; + ULONG Access3:2; + ULONG BaseAddress:20; + } Small; + struct + { + ULONG Type:2; + ULONG Buffered:1; + ULONG Cached:1; + ULONG Access0:2; + ULONG Ignored:4; + ULONG BaseAddress:22; + } Tiny; =
+ } L2; + ULONG AsUlong; + }; } HARDWARE_PTE_ARM, *PHARDWARE_PTE_ARM; =
typedef struct _MMPTE_SOFTWARE @@ -117,19 +185,87 @@ =
typedef struct _MMPTE_HARDWARE { - ULONG Valid:1; - ULONG Write:1; - ULONG Owner:1; - ULONG WriteThrough:1; - ULONG CacheDisable:1; - ULONG Accessed:1; - ULONG Dirty:1; - ULONG LargePage:1; - ULONG Global:1; - ULONG CopyOnWrite:1; - ULONG Prototype:1; - ULONG reserved:1; - ULONG PageFrameNumber:20; + union + { + union + { + struct + { + ULONG Type:2; + ULONG Unused:30; + } Fault; + struct + { + ULONG Type:2; + ULONG Ignored:2; + ULONG Reserved:1; + ULONG Domain:4; + ULONG Ignored1:1; + ULONG BaseAddress:22; + } Coarse; + struct + { + ULONG Type:2; + ULONG Buffered:1; + ULONG Cached:1; + ULONG Reserved:1; + ULONG Domain:4; + ULONG Ignored:1; + ULONG Access:2; + ULONG Ignored1:8; + ULONG BaseAddress:12; + } Section; + struct + { + ULONG Type:2; + ULONG Reserved:3; + ULONG Domain:4; + ULONG Ignored:3; + ULONG BaseAddress:20; + } Fine; + } L1; + union + { + struct + { + ULONG Type:2; + ULONG Unused:30; + } Fault; + struct + { + ULONG Type:2; + ULONG Buffered:1; + ULONG Cached:1; + ULONG Access0:2; + ULONG Access1:2; + ULONG Access2:2; + ULONG Access3:2; + ULONG Ignored:4; + ULONG BaseAddress:16; + } Large; + struct + { + ULONG Type:2; + ULONG Buffered:1; + ULONG Cached:1; + ULONG Access0:2; + ULONG Access1:2; + ULONG Access2:2; + ULONG Access3:2; + ULONG BaseAddress:20; + } Small; + struct + { + ULONG Type:2; + ULONG Buffered:1; + ULONG Cached:1; + ULONG Access0:2; + ULONG Ignored:4; + ULONG BaseAddress:22; + } Tiny; =
+ } L2; + ULONG AsUlong; + }; } MMPTE_HARDWARE, *PMMPTE_HARDWARE; =
//
Modified: trunk/reactos/ntoskrnl/include/internal/arm/ke.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/include/inte= rnal/arm/ke.h?rev=3D32640&r1=3D32639&r2=3D32640&view=3Ddiff =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D --- trunk/reactos/ntoskrnl/include/internal/arm/ke.h (original) +++ trunk/reactos/ntoskrnl/include/internal/arm/ke.h Mon Mar 10 12:27:14 20= 08 @@ -174,5 +174,6 @@ ); =
#define KeArchInitThreadWithContext KeArmInitThreadWithContext +#define KiSystemStartupReal KiSystemStartup =
#endif
Modified: trunk/reactos/ntoskrnl/include/internal/arm/mm.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/include/inte= rnal/arm/mm.h?rev=3D32640&r1=3D32639&r2=3D32640&view=3Ddiff =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D --- trunk/reactos/ntoskrnl/include/internal/arm/mm.h (original) +++ trunk/reactos/ntoskrnl/include/internal/arm/mm.h Mon Mar 10 12:27:14 20= 08 @@ -113,6 +113,7 @@ typedef struct _ARM_COARSE_PAGE_TABLE { ARM_PTE Pte[256]; + ULONG Padding[768]; } ARM_COARSE_PAGE_TABLE, *PARM_COARSE_PAGE_TABLE; =
typedef enum _ARM_L1_PTE_TYPE
Modified: trunk/reactos/ntoskrnl/ke/arm/arm_kprintf.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ke/arm/arm_k= printf.c?rev=3D32640&r1=3D32639&r2=3D32640&view=3Ddiff =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D --- trunk/reactos/ntoskrnl/ke/arm/arm_kprintf.c (original) +++ trunk/reactos/ntoskrnl/ke/arm/arm_kprintf.c Mon Mar 10 12:27:14 2008 @@ -17,7 +17,7 @@ // // UART Registers // -#define UART_BASE (void*)0xc00f1000 /* HACK: freeldr mapped it here */ +#define UART_BASE (void*)0xe00f1000 /* HACK: freeldr mapped it here */ =
#define UART_PL01x_DR (UART_BASE + 0x00) #define UART_PL01x_RSR (UART_BASE + 0x04)
Modified: trunk/reactos/ntoskrnl/ke/freeldr.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ke/freeldr.c= ?rev=3D32640&r1=3D32639&r2=3D32640&view=3Ddiff =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D --- trunk/reactos/ntoskrnl/ke/freeldr.c (original) +++ trunk/reactos/ntoskrnl/ke/freeldr.c Mon Mar 10 12:27:14 2008 @@ -771,7 +771,7 @@ if (MdBlock) { /* If it contains our limit as well, break out early */ - if ((MdBlock->PageCount + MdBlock->BasePage) > AlignedLimit) b= reak; + if ((MdBlock->PageCount + MdBlock->BasePage) >=3D AlignedLimit= ) break; } =
/* Loop the memory list */
Modified: trunk/reactos/ntoskrnl/mm/arm/stubs.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/mm/arm/stubs= .c?rev=3D32640&r1=3D32639&r2=3D32640&view=3Ddiff =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D --- trunk/reactos/ntoskrnl/mm/arm/stubs.c (original) +++ trunk/reactos/ntoskrnl/mm/arm/stubs.c Mon Mar 10 12:27:14 2008 @@ -20,6 +20,29 @@ while (TRUE); \ } =
+// +// Take 0x80812345 and extract: +// PTE_BASE[0x808][0x12] +// +#define MiGetPteAddress(x) \ + (PMMPTE)(PTE_BASE + (((ULONG)(x) >> 20) << 12) + ((((ULONG)(x) >> 12) = & 0xFF) << 2)) + +#define MiGetPdeAddress(x) \ + (PMMPTE)(PDE_BASE + (((ULONG)(x) >> 20) << 2)) + +#define MiGetPdeOffset(x) (((ULONG)(x)) >> 22) + +#define PTE_BASE 0xC0000000 +#define PDE_BASE 0xC1000000 +#define HYPER_SPACE ((PVOID)0xC1100000) + +ULONG MmGlobalKernelPageDirectory[1024]; +MMPTE MiArmTemplatePte, MiArmTemplatePde; + +VOID +KiFlushSingleTb(IN BOOLEAN Invalid, + IN PVOID Virtual); + /* FUNCTIONS *************************************************************= *****/ =
VOID @@ -71,10 +94,9 @@ MmGetPageDirectory(VOID) { // - // TODO - // - UNIMPLEMENTED; - return 0; + // Return the TTB + // + return (PULONG)KeArmTranslationTableRegisterGet().AsUlong; } =
=
@@ -96,10 +118,65 @@ MmDeletePageTable(IN PEPROCESS Process, IN PVOID Address) { - // - // TODO - // - UNIMPLEMENTED; + PMMPTE PointerPde; + =
+ // + // Not valid for kernel addresses + // + DPRINT1("MmDeletePageTable(%p, %p)\n", Process, Address); + ASSERT(Address < MmSystemRangeStart); + =
+ // + // Check if this is for a different process + // + if ((Process) && (Process !=3D PsGetCurrentProcess())) + { + // + // TODO + // + UNIMPLEMENTED; + return; + } + =
+ // + // Get the PDE + // + PointerPde =3D MiGetPdeAddress(Address); + + // + // On ARM, we use a section mapping for the original low-memory mapping + // + if ((Address) || (PointerPde->u.Hard.L1.Section.Type !=3D SectionPte)) + { + // + // Make sure it's valid + // + ASSERT(PointerPde->u.Hard.L1.Coarse.Type =3D=3D CoarsePte); + } + =
+ // + // Clear the PDE + // + PointerPde->u.Hard.AsUlong =3D 0; + ASSERT(PointerPde->u.Hard.L1.Fault.Type =3D=3D FaultPte); + =
+ // + // Check if this is a kernel PDE + // + if ((PointerPde >=3D (PMMPTE)PTE_BASE) && (PointerPde < (PMMPTE)PTE_BA= SE + (1024 * 1024))) + { + // + // Invalidate the TLB entry + // + KiFlushSingleTb(TRUE, Address); + } + else + { + // + // Process PDE, unmap it from hyperspace (will also invalidate TLB= entry) + // + MmDeleteHyperspaceMapping((PVOID)PAGE_ROUND_DOWN(PointerPde)); + } } =
PFN_TYPE @@ -215,11 +292,38 @@ MmIsPagePresent(IN PEPROCESS Process, IN PVOID Address) { - // - // TODO - // - UNIMPLEMENTED; - return 0; + PMMPTE Pte; + =
+ // + // Check if this is for a different process + // + if ((Process) && (Process !=3D PsGetCurrentProcess())) + { + // + // TODO + // + UNIMPLEMENTED; + return 0; + } + + // + // Get the PDE + // + Pte =3D MiGetPdeAddress(Address); + if (Pte->u.Hard.L1.Fault.Type !=3D FaultPte) + { + // + // Get the PTE + // + Pte =3D MiGetPteAddress(Address); + } + =
+ // + // Return whether or not it's valid + // + return (Pte->u.Hard.L1.Fault.Type !=3D FaultPte); + =
+ =
} =
BOOLEAN @@ -237,15 +341,107 @@ NTSTATUS NTAPI MmCreateVirtualMappingForKernel(IN PVOID Address, - IN ULONG flProtect, - IN PPFN_TYPE Pages, + IN ULONG Protection, + IN PPFN_NUMBER Pages, IN ULONG PageCount) { - // - // TODO - // - UNIMPLEMENTED; - return 0; + PMMPTE PointerPte, LastPte, PointerPde, LastPde; + MMPTE TempPte, TempPde; + NTSTATUS Status; + PFN_NUMBER Pfn; + DPRINT1("MmCreateVirtualMappingForKernel(%x, %x, %x, %d)\n", + Address, Protection, *Pages, PageCount); + ASSERT(Address >=3D MmSystemRangeStart); + + // + // Get our templates + // + TempPte =3D MiArmTemplatePte; + TempPde =3D MiArmTemplatePde; + + // + // Check if we have PDEs for this region + // + PointerPde =3D MiGetPdeAddress(Address); + LastPde =3D PointerPde + (PageCount / 256); + while (PointerPde <=3D LastPde) + { + // + // Check if we need to allocate the PDE + // + if (PointerPde->u.Hard.L1.Fault.Type =3D=3D FaultPte) + { + // + // Request a page + // + Status =3D MmRequestPageMemoryConsumer(MC_NPPOOL, FALSE, &Pfn); + if (!NT_SUCCESS(Status)) return Status; + =
+ // + // Setup the PFN + // + TempPde.u.Hard.L1.Coarse.BaseAddress =3D (Pfn << PAGE_SHIFT) >=
CPT_SHIFT;
+ =
+ // + // Write the PDE + // + ASSERT(PointerPde->u.Hard.L1.Fault.Type =3D=3D FaultPte); + ASSERT(TempPde.u.Hard.L1.Coarse.Type =3D=3D CoarsePte); + *PointerPde =3D TempPde; + =
+ // + // Get the PTE for this 1MB region + // + PointerPte =3D MiGetPteAddress(MiGetPteAddress(Address)); + =
+ // + // Write the PFN of the PDE + // + TempPte.u.Hard.L2.Small.BaseAddress =3D Pfn; + + // + // Write the PTE + // + ASSERT(PointerPte->u.Hard.L2.Fault.Type =3D=3D FaultPte); + ASSERT(TempPte.u.Hard.L2.Small.Type =3D=3D SmallPte); + *PointerPte =3D TempPte; + } + =
+ // + // Next + // + PointerPde++; + } + =
+ // + // Get start and end address and loop each PTE + // + PointerPte =3D MiGetPteAddress(Address); + LastPte =3D PointerPte + PageCount - 1; + while (PointerPte <=3D LastPte) + { + // + // Set the PFN + // + TempPte.u.Hard.L2.Small.BaseAddress =3D *Pages++; + =
+ // + // Write the PTE + // + ASSERT(PointerPte->u.Hard.L2.Fault.Type =3D=3D FaultPte); + ASSERT(TempPte.u.Hard.L2.Small.Type =3D=3D SmallPte); + *PointerPte =3D TempPte; + =
+ // + // Next + // + PointerPte++; + } + =
+ // + // All done + // + return STATUS_SUCCESS; } =
NTSTATUS @@ -265,10 +461,27 @@ NTAPI MmCreateVirtualMappingUnsafe(IN PEPROCESS Process, IN PVOID Address, - IN ULONG flProtect, + IN ULONG Protection, IN PPFN_TYPE Pages, IN ULONG PageCount) { + DPRINT1("MmCreateVirtualMappingUnsafe(%p %x, %x, %x, %d)\n", + Process, Address, Protection, *Pages, PageCount); + =
+ // + // Are we only handling the kernel? + // + if (!Process) + { + // + // Call the kernel version + // + return MmCreateVirtualMappingForKernel(Address, + Protection, + Pages, + PageCount); + } + =
// // TODO // @@ -280,15 +493,33 @@ NTAPI MmCreateVirtualMapping(IN PEPROCESS Process, IN PVOID Address, - IN ULONG flProtect, + IN ULONG Protection, IN PPFN_TYPE Pages, IN ULONG PageCount) { - // - // TODO - // - UNIMPLEMENTED; - return 0; + ULONG i; + DPRINT1("MmCreateVirtualMapping(%p %x, %x, %x, %d)\n", + Process, Address, Protection, *Pages, PageCount); + =
+ // + // Loop each page + // + for (i =3D 0; i < PageCount; i++) + { + // + // Make sure the page is marked as in use + // + ASSERT(MmIsPageInUse(Pages[i])); + } + =
+ // + // Call the unsafe version + // + return MmCreateVirtualMappingUnsafe(Process, + Address, + Protection, + Pages, + PageCount); } =
ULONG @@ -307,12 +538,12 @@ NTAPI MmSetPageProtect(IN PEPROCESS Process, IN PVOID Address, - IN ULONG flProtect) -{ - // - // TODO - // - UNIMPLEMENTED; + IN ULONG Protection) +{ + // + // We don't enforce any protection on the pages -- they are all RWX + // + return; } =
/* @@ -335,6 +566,130 @@ NTAPI MmCreateHyperspaceMapping(IN PFN_TYPE Page) { + PMMPTE PointerPte, FirstPte, LastPte; + MMPTE TempPte; + PVOID Address; + DPRINT1("MmCreateHyperspaceMapping(%lx)\n", Page); + + // + // Loop hyperspace PTEs (1MB) + // + FirstPte =3D PointerPte =3D MiGetPteAddress(HYPER_SPACE); + LastPte =3D PointerPte + 256; + while (PointerPte <=3D LastPte) + { + // + // Find a free slot + // + if (PointerPte->u.Hard.L2.Fault.Type =3D=3D FaultPte) + { + // + // Use this entry + // + break; + } + =
+ // + // Try the next one + // + PointerPte++; + } + =
+ // + // Check if we didn't find anything + // + if (PointerPte > LastPte) return NULL; + =
+ // + // Create the mapping + // + TempPte =3D MiArmTemplatePte; + TempPte.u.Hard.L2.Small.BaseAddress =3D Page; + ASSERT(PointerPte->u.Hard.L2.Fault.Type =3D=3D FaultPte); + ASSERT(TempPte.u.Hard.L2.Small.Type =3D=3D SmallPte); + *PointerPte =3D TempPte; + + // + // Return the address + // + Address =3D HYPER_SPACE + ((PointerPte - FirstPte) * PAGE_SIZE); + KiFlushSingleTb(FALSE, Address); + DPRINT1("MmCreateHyperspaceMapping(%lx)\n", Address); + return Address; +} + +PFN_TYPE +NTAPI +MmDeleteHyperspaceMapping(IN PVOID Address) +{ + PFN_TYPE Pfn; + PMMPTE PointerPte; + DPRINT1("MmDeleteHyperspaceMapping(%lx)\n", Address); + =
+ // + // Get the PTE + // + PointerPte =3D MiGetPteAddress(Address); + ASSERT(PointerPte->u.Hard.L2.Small.Type =3D=3D SmallPte); + =
+ // + // Save the PFN + // + Pfn =3D PointerPte->u.Hard.L2.Small.BaseAddress; + =
+ // + // Destroy the PTE + // + PointerPte->u.Hard.AsUlong =3D 0; + ASSERT(PointerPte->u.Hard.L2.Fault.Type =3D=3D FaultPte); + =
+ // + // Flush the TLB entry and return the PFN + // + KiFlushSingleTb(TRUE, Address); + return Pfn; + =
+} + +VOID +NTAPI +MmInitGlobalKernelPageDirectory(VOID) +{ + ULONG i; + PULONG CurrentPageDirectory =3D (PULONG)PDE_BASE; + =
+ // + // Good place to setup template PTE/PDEs. + // We are lazy and pick a known-good PTE + // + MiArmTemplatePte =3D *MiGetPteAddress(0x80000000); + MiArmTemplatePde =3D *MiGetPdeAddress(0x80000000); + + // + // Loop the 2GB of address space which belong to the kernel + // + for (i =3D MiGetPdeOffset(MmSystemRangeStart); i < 1024; i++) + { + // + // Check if we have an entry for this already + // + if ((i !=3D MiGetPdeOffset(PTE_BASE)) && + (i !=3D MiGetPdeOffset(HYPER_SPACE)) && + (!MmGlobalKernelPageDirectory[i]) && + (CurrentPageDirectory[i])) + { + // + // We don't, link it in our global page directory + // + MmGlobalKernelPageDirectory[i] =3D CurrentPageDirectory[i]; + } + } +} + +ULONG +NTAPI +MiGetUserPageDirectoryCount(VOID) +{ // // TODO // @@ -342,46 +697,59 @@ return 0; } =
-PFN_TYPE -NTAPI -MmDeleteHyperspaceMapping(IN PVOID Address) -{ - PFN_TYPE Pfn =3D {0}; - =
- // - // TODO - // - UNIMPLEMENTED; - return Pfn; -} - -VOID -NTAPI -MmInitGlobalKernelPageDirectory(VOID) -{ - // - // TODO - // - UNIMPLEMENTED; -} - -ULONG -NTAPI -MiGetUserPageDirectoryCount(VOID) -{ - // - // TODO - // - UNIMPLEMENTED; - return 0; -} - VOID NTAPI MiInitPageDirectoryMap(VOID) { - // - // TODO - // - UNIMPLEMENTED; -} + MEMORY_AREA* MemoryArea =3D NULL; + PHYSICAL_ADDRESS BoundaryAddressMultiple; + PVOID BaseAddress; + NTSTATUS Status; + DPRINT1("MiInitPageDirectoryMap()\n"); + + // + // Create memory area for the PTE area + // + BoundaryAddressMultiple.QuadPart =3D 0; + BaseAddress =3D (PVOID)PTE_BASE; + Status =3D MmCreateMemoryArea(MmGetKernelAddressSpace(), + MEMORY_AREA_SYSTEM, + &BaseAddress, + 0x1000000, + PAGE_READWRITE, + &MemoryArea, + TRUE, + 0, + BoundaryAddressMultiple); + ASSERT(NT_SUCCESS(Status)); + + // + // Create memory area for the PDE area + // + BaseAddress =3D (PVOID)PDE_BASE; + Status =3D MmCreateMemoryArea(MmGetKernelAddressSpace(), + MEMORY_AREA_SYSTEM, + &BaseAddress, + 0x100000, + PAGE_READWRITE, + &MemoryArea, + TRUE, + 0, + BoundaryAddressMultiple); + ASSERT(NT_SUCCESS(Status)); + =
+ // + // And finally, hyperspace + // + BaseAddress =3D (PVOID)HYPER_SPACE; + Status =3D MmCreateMemoryArea(MmGetKernelAddressSpace(), + MEMORY_AREA_SYSTEM, + &BaseAddress, + PAGE_SIZE, + PAGE_READWRITE, + &MemoryArea, + TRUE, + 0, + BoundaryAddressMultiple); + ASSERT(NT_SUCCESS(Status)); +}
Modified: trunk/reactos/ntoskrnl/mm/mminit.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/mm/mminit.c?= rev=3D32640&r1=3D32639&r2=3D32640&view=3Ddiff =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D --- trunk/reactos/ntoskrnl/mm/mminit.c (original) +++ trunk/reactos/ntoskrnl/mm/mminit.c Mon Mar 10 12:27:14 2008 @@ -347,9 +347,7 @@ NextEntry =3D NextEntry->Flink) { Md =3D CONTAINING_RECORD(NextEntry, MEMORY_ALLOCATION_DESCRIPTOR, = ListEntry); - if (Md->MemoryType =3D=3D LoaderBootDriver || - Md->MemoryType =3D=3D LoaderSystemCode || - Md->MemoryType =3D=3D LoaderHalCode) + if (Md->MemoryType !=3D LoaderFree) { if (Md->BasePage+Md->PageCount > LastKrnlPhysAddr) LastKrnlPhysAddr =3D Md->BasePage+Md->PageCount; =
@@ -432,10 +430,13 @@ MmPagedPoolBase =3D (PVOID)PAGE_ROUND_UP((ULONG_PTR)MiNonPagedPoolStar= t + MiNonPagedPoolLength); MmPagedPoolSize =3D MM_PAGED_POOL_SIZE; + =
/* Dump kernel memory layout */ MiDbgKernelLayout(); + =
/* Initialize the page list */ MmInitializePageList(); + =
/* Unmap low memory */ MmDeletePageTable(NULL, 0); =