diff --git a/reactos/boot/freeldr/freeldr/arch/arm/boot.s b/reactos/boot/freeldr/freeldr/arch/arm/boot.s index 0e5da3ac279..bafcd28de61 100644 --- a/reactos/boot/freeldr/freeldr/arch/arm/boot.s +++ b/reactos/boot/freeldr/freeldr/arch/arm/boot.s @@ -69,4 +69,24 @@ BootStackEnd: .section pagedata .global ArmTranslationTable ArmTranslationTable: - .space 0x4000 + .space 0x4000 // 0x00000000->0xFFFFFFFF + +.global BootTranslationTable +BootTranslationTable: + .space 0x0400 // 0x00000000->0x800FFFFF + .space 0x0400 // 0x00100000->0x801FFFFF + .space 0x0400 // 0x00200000->0x802FFFFF + .space 0x0400 // 0x00300000->0x803FFFFF + .space 0x0400 // 0x00400000->0x804FFFFF + .space 0x0400 // 0x00500000->0x805FFFFF + .space 0x0400 // 0x00600000->0x806FFFFF + .space 0x0400 // 0x00700000->0x807FFFFF + +.global KernelTranslationTable +KernelTranslationTable: + .space 0x0400 // 0x00800000->0x808FFFFF + .space 0x0400 // 0x00900000->0x809FFFFF + .space 0x0400 // 0x00A00000->0x80AFFFFF + .space 0x0400 // 0x00B00000->0x80BFFFFF + .space 0x0400 // 0x00C00000->0x80CFFFFF + .space 0x0400 // 0x00D00000->0x80DFFFFF diff --git a/reactos/boot/freeldr/freeldr/arch/arm/loader.c b/reactos/boot/freeldr/freeldr/arch/arm/loader.c index ecbe87a7d8b..76cc76c9deb 100644 --- a/reactos/boot/freeldr/freeldr/arch/arm/loader.c +++ b/reactos/boot/freeldr/freeldr/arch/arm/loader.c @@ -16,15 +16,17 @@ /* GLOBALS ********************************************************************/ ULONG PageDirectoryStart, PageDirectoryEnd; -LOADER_PARAMETER_BLOCK ArmLoaderBlock; +PLOADER_PARAMETER_BLOCK ArmLoaderBlock; CHAR ArmCommandLine[256]; CHAR ArmArcBootPath[64]; CHAR ArmArcHalPath[64]; CHAR ArmNtHalPath[64]; CHAR ArmNtBootPath[64]; -LOADER_PARAMETER_EXTENSION ArmExtension; +PLOADER_PARAMETER_EXTENSION ArmExtension; extern ARM_TRANSLATION_TABLE ArmTranslationTable; +extern ARM_COARSE_PAGE_TABLE BootTranslationTable, KernelTranslationTable; extern ROS_KERNEL_ENTRY_POINT KernelEntryPoint; +extern ULONG_PTR KernelBase; ULONG SizeBits[] = { @@ -65,21 +67,21 @@ ArmSetupPageDirectory(VOID) ARM_TTB_REGISTER TtbRegister; ARM_DOMAIN_REGISTER DomainRegister; ARM_PTE Pte; - ULONG i; - PARM_TRANSLATION_TABLE TranslationTable; + ULONG i, j; + PARM_TRANSLATION_TABLE MasterTable; + PARM_COARSE_PAGE_TABLE BootTable, KernelTable; // - // Allocate translation table buffer. - // During bootstrap, this will be a simple L1 (Master) Page Table with - // Section entries for KSEG0 and the first MB of RAM. + // Get the PDEs that we will use // - TranslationTable = &ArmTranslationTable; - if (!TranslationTable) return; + MasterTable = &ArmTranslationTable; + BootTable = &BootTranslationTable; + KernelTable = &KernelTranslationTable; // - // Set it as the TTB + // Set the master L1 PDE as the TTB // - TtbRegister.AsUlong = (ULONG)TranslationTable; + TtbRegister.AsUlong = (ULONG)MasterTable; ASSERT(TtbRegister.Reserved == 0); KeArmTranslationTableRegisterSet(TtbRegister); @@ -93,10 +95,10 @@ ArmSetupPageDirectory(VOID) // // Set Fault PTEs everywhere // - RtlZeroMemory(TranslationTable, 4096 * sizeof(ARM_PTE)); + RtlZeroMemory(MasterTable, sizeof(ARM_TRANSLATION_TABLE)); // - // Build the template PTE + // Identity map the first MB of memory // Pte.L1.Section.Type = SectionPte; Pte.L1.Section.Buffered = FALSE; @@ -106,32 +108,125 @@ ArmSetupPageDirectory(VOID) Pte.L1.Section.Access = SupervisorAccess; Pte.L1.Section.BaseAddress = 0; Pte.L1.Section.Ignored = Pte.L1.Section.Ignored1 = 0; - - // - // Map KSEG0 (0x80000000 - 0xA0000000) to 0x00000000 - 0x20000000 - // In this way, the KERNEL_PHYS_ADDR (0x800000) becomes 0x80800000 - // which is the entrypoint, just like on x86. - // - for (i = (KSEG0_BASE >> TTB_SHIFT); i < ((KSEG0_BASE + 0x20000000) >> TTB_SHIFT); i++) - { - // - // Write PTE and update the base address (next MB) for the next one - // - TranslationTable->Pte[i] = Pte; - Pte.L1.Section.BaseAddress++; - } - - // - // Identity map the first MB of memory as well - // - Pte.L1.Section.BaseAddress = 0; - TranslationTable->Pte[0] = Pte; + MasterTable->Pte[0] = Pte; // // Map the page in MMIO space that contains the serial port into virtual memory // - Pte.L1.Section.BaseAddress = ArmBoardBlock->UartRegisterBase >> TTB_SHIFT; - TranslationTable->Pte[UART_VIRTUAL >> TTB_SHIFT] = Pte; + Pte.L1.Section.BaseAddress = ArmBoardBlock->UartRegisterBase >> PDE_SHIFT; + MasterTable->Pte[UART_VIRTUAL >> PDE_SHIFT] = Pte; + + // + // Create template PTE for the coarse page tables which map the first 8MB + // + Pte.L1.Coarse.Type = CoarsePte; + Pte.L1.Coarse.Domain = Domain0; + Pte.L1.Coarse.Reserved = 1; // ARM926EJ-S manual recommends setting to 1 + Pte.L1.Coarse.BaseAddress = (ULONG)BootTable >> CPT_SHIFT; + Pte.L1.Coarse.Ignored = Pte.L1.Coarse.Ignored1 = 0; + + // + // Map 0x00000000 - 0x007FFFFF to 0x80000000 - 0x807FFFFF. + // This is where the freeldr boot structures are located, and we need them. + // + for (i = (KSEG0_BASE >> PDE_SHIFT); i < ((KSEG0_BASE + 0x800000) >> PDE_SHIFT); i++) + { + // + // Write PTE and update the base address (next MB) for the next one + // + MasterTable->Pte[i] = Pte; + Pte.L1.Coarse.BaseAddress++; + } + + // + // Now create the template PTE for the coarse page tables for the next 6MB + // + Pte.L1.Coarse.BaseAddress = (ULONG)KernelTable >> CPT_SHIFT; + TuiPrintf("Coarse Table at: %x\n", KernelTable); + TuiPrintf("Coarse Table at: %x\n", Pte.L1.Coarse.BaseAddress); + + // + // Map 0x00800000 - 0x00DFFFFF to 0x80800000 - 0x80DFFFFF + // In this way, the KERNEL_PHYS_ADDR (0x800000) becomes 0x80800000 + // which is the kernel virtual base address, just like on x86. + // + ASSERT(KernelBase == 0x80800000); + for (i = (KernelBase >> PDE_SHIFT); i < ((KernelBase + 0x600000) >> PDE_SHIFT); i++) + { + // + // Write PTE and update the base address (next MB) for the next one + // + MasterTable->Pte[i] = Pte; + Pte.L1.Coarse.BaseAddress++; + } + + // + // Now build the template PTE for the pages mapping the first 8MB + // + Pte.L2.Small.Type = SmallPte; + Pte.L2.Small.Buffered = Pte.L2.Small.Cached = 0; + Pte.L2.Small.Access0 = + Pte.L2.Small.Access1 = + Pte.L2.Small.Access2 = + Pte.L2.Small.Access3 = SupervisorAccess; + Pte.L2.Small.BaseAddress = 0; + + // + // Loop each boot coarse page table (i). + // Each PDE describes 1MB. We're mapping an area of 8MB, so 8 times. + // + for (i = 0; i < 8; i++) + { + // + // Loop and set each the PTE (j). + // Each PTE describes 4KB. We're mapping an area of 1MB, so 256 times. + // + for (j = 0; j < (PDE_SIZE / PAGE_SIZE); j++) + { + // + // Write PTE and update the base address (next MB) for the next one + // + BootTable->Pte[j] = Pte; + Pte.L2.Small.BaseAddress++; + } + + // + // Next iteration + // + BootTable++; + } + + // + // Now create the template PTE for the pages mapping the next 6MB + // + Pte.L2.Small.BaseAddress = (ULONG)KERNEL_BASE_PHYS >> PTE_SHIFT; + TuiPrintf("First Kernel PFN at: %x\n", Pte.L2.Small.BaseAddress); + + // + // Loop each kernel coarse page table (i). + // Each PDE describes 1MB. We're mapping an area of 6MB, so 6 times. + // + for (i = 0; i < 6; i++) + { + // + // Loop and set each the PTE (j). + // Each PTE describes 4KB. We're mapping an area of 1MB, so 256 times. + // + for (j = 0; j < (PDE_SIZE / PAGE_SIZE); j++) + { + // + // Write PTE and update the base address (next MB) for the next one + // + KernelTable->Pte[j] = Pte; + Pte.L2.Small.BaseAddress++; + } + + // + // Next iteration + // + KernelTable++; + TuiPrintf("Coarse Table at: %x\n", KernelTable); + } } VOID @@ -153,13 +248,13 @@ ArmSetupPagingAndJump(IN ULONG Magic) // ArmBoardBlock->UartRegisterBase = UART_VIRTUAL | (ArmBoardBlock->UartRegisterBase & - ((1 << TTB_SHIFT) - 1)); + ((1 << PDE_SHIFT) - 1)); TuiPrintf("Mapped serial port to 0x%x\n", ArmBoardBlock->UartRegisterBase); // // Jump to Kernel // - (*KernelEntryPoint)(Magic, (PVOID)&ArmLoaderBlock); + (*KernelEntryPoint)(Magic, (PVOID)ArmLoaderBlock); } VOID @@ -169,18 +264,28 @@ ArmPrepareForReactOS(IN BOOLEAN Setup) PVOID Base; PCHAR BootPath, HalPath; + // + // Allocate the loader block and extension + // + ArmLoaderBlock = MmAllocateMemoryWithType(sizeof(LOADER_PARAMETER_BLOCK), + LoaderOsloaderHeap); + if (!ArmLoaderBlock) return; + ArmExtension = MmAllocateMemoryWithType(sizeof(LOADER_PARAMETER_EXTENSION), + LoaderOsloaderHeap); + if (!ArmExtension) return; + // // Initialize the loader block // - InitializeListHead(&ArmLoaderBlock.BootDriverListHead); - InitializeListHead(&ArmLoaderBlock.LoadOrderListHead); - InitializeListHead(&ArmLoaderBlock.MemoryDescriptorListHead); + InitializeListHead(&ArmLoaderBlock->BootDriverListHead); + InitializeListHead(&ArmLoaderBlock->LoadOrderListHead); + InitializeListHead(&ArmLoaderBlock->MemoryDescriptorListHead); // // Setup the extension and setup block // - ArmLoaderBlock.Extension = &ArmExtension; - ArmLoaderBlock.SetupLdrBlock = NULL; + ArmLoaderBlock->Extension = ArmExtension; + ArmLoaderBlock->SetupLdrBlock = NULL; // // TODO: Setup memory descriptors @@ -209,7 +314,7 @@ ArmPrepareForReactOS(IN BOOLEAN Setup) // // Make a copy of the command line // - ArmLoaderBlock.LoadOptions = ArmCommandLine; + ArmLoaderBlock->LoadOptions = ArmCommandLine; strcpy(ArmCommandLine, reactos_kernel_cmdline); // @@ -222,7 +327,7 @@ ArmPrepareForReactOS(IN BOOLEAN Setup) // Set the ARC Boot Path // strncpy(ArmArcBootPath, ArmCommandLine, 63); - ArmLoaderBlock.ArcBootDeviceName = ArmArcBootPath; + ArmLoaderBlock->ArcBootDeviceName = ArmArcBootPath; // // The rest of the string is the NT path @@ -232,77 +337,77 @@ ArmPrepareForReactOS(IN BOOLEAN Setup) ArmNtBootPath[0] = '\\'; strncat(ArmNtBootPath, BootPath + 1, 63); strcat(ArmNtBootPath,"\\"); - ArmLoaderBlock.NtBootPathName = ArmNtBootPath; + ArmLoaderBlock->NtBootPathName = ArmNtBootPath; // // Set the HAL paths // strncpy(ArmArcHalPath, ArmArcBootPath, 63); - ArmLoaderBlock.ArcHalDeviceName = ArmArcHalPath; + ArmLoaderBlock->ArcHalDeviceName = ArmArcHalPath; strcpy(ArmNtHalPath, "\\"); - ArmLoaderBlock.NtHalPathName = ArmNtHalPath; + ArmLoaderBlock->NtHalPathName = ArmNtHalPath; /* Use this new command line */ - strncpy(ArmLoaderBlock.LoadOptions, HalPath + 2, 255); + strncpy(ArmLoaderBlock->LoadOptions, HalPath + 2, 255); /* Parse it and change every slash to a space */ - BootPath = ArmLoaderBlock.LoadOptions; + BootPath = ArmLoaderBlock->LoadOptions; do {if (*BootPath == '/') *BootPath = ' ';} while (*BootPath++); // // Setup cache information // CacheReg = KeArmCacheRegisterGet(); - ArmLoaderBlock.u.Arm.FirstLevelDcacheSize = SizeBits[CacheReg.DSize]; - ArmLoaderBlock.u.Arm.FirstLevelDcacheFillSize = LenBits[CacheReg.DLength]; - ArmLoaderBlock.u.Arm.FirstLevelDcacheFillSize <<= 2; - ArmLoaderBlock.u.Arm.FirstLevelIcacheSize = SizeBits[CacheReg.ISize]; - ArmLoaderBlock.u.Arm.FirstLevelIcacheFillSize = LenBits[CacheReg.ILength]; - ArmLoaderBlock.u.Arm.FirstLevelIcacheFillSize <<= 2; - ArmLoaderBlock.u.Arm.SecondLevelDcacheSize = - ArmLoaderBlock.u.Arm.SecondLevelDcacheFillSize = - ArmLoaderBlock.u.Arm.SecondLevelIcacheSize = - ArmLoaderBlock.u.Arm.SecondLevelIcacheFillSize = 0; - + ArmLoaderBlock->u.Arm.FirstLevelDcacheSize = SizeBits[CacheReg.DSize]; + ArmLoaderBlock->u.Arm.FirstLevelDcacheFillSize = LenBits[CacheReg.DLength]; + ArmLoaderBlock->u.Arm.FirstLevelDcacheFillSize <<= 2; + ArmLoaderBlock->u.Arm.FirstLevelIcacheSize = SizeBits[CacheReg.ISize]; + ArmLoaderBlock->u.Arm.FirstLevelIcacheFillSize = LenBits[CacheReg.ILength]; + ArmLoaderBlock->u.Arm.FirstLevelIcacheFillSize <<= 2; + ArmLoaderBlock->u.Arm.SecondLevelDcacheSize = + ArmLoaderBlock->u.Arm.SecondLevelDcacheFillSize = + ArmLoaderBlock->u.Arm.SecondLevelIcacheSize = + ArmLoaderBlock->u.Arm.SecondLevelIcacheFillSize = 0; + // // Allocate the Interrupt stack // Base = MmAllocateMemoryWithType(KERNEL_STACK_SIZE, LoaderStartupDpcStack); - ArmLoaderBlock.u.Arm.InterruptStack = KSEG0_BASE | (ULONG)Base; + ArmLoaderBlock->u.Arm.InterruptStack = KSEG0_BASE | (ULONG)Base; // // Allocate the Kernel Boot stack // Base = MmAllocateMemoryWithType(KERNEL_STACK_SIZE, LoaderStartupKernelStack); - ArmLoaderBlock.KernelStack = KSEG0_BASE | (ULONG)Base; + ArmLoaderBlock->KernelStack = KSEG0_BASE | (ULONG)Base; // // Allocate the Abort stack // Base = MmAllocateMemoryWithType(KERNEL_STACK_SIZE, LoaderStartupPanicStack); - ArmLoaderBlock.u.Arm.PanicStack = KSEG0_BASE | (ULONG)Base; + ArmLoaderBlock->u.Arm.PanicStack = KSEG0_BASE | (ULONG)Base; // // Allocate the PCR page -- align it to 1MB (we only need 4KB) // Base = MmAllocateMemoryWithType(2 * 1024 * 1024, LoaderStartupPcrPage); Base = (PVOID)ROUND_UP(Base, 1 * 1024 * 1024); - ArmLoaderBlock.u.Arm.PcrPage = (ULONG)Base >> TTB_SHIFT; + ArmLoaderBlock->u.Arm.PcrPage = (ULONG)Base >> PDE_SHIFT; // // Allocate PDR pages -- align them to 1MB (we only need 3xKB) // Base = MmAllocateMemoryWithType(4 * 1024 * 1024, LoaderStartupPdrPage); Base = (PVOID)ROUND_UP(Base, 1 * 1024 * 1024); - ArmLoaderBlock.u.Arm.PdrPage = (ULONG)Base >> TTB_SHIFT; + ArmLoaderBlock->u.Arm.PdrPage = (ULONG)Base >> PDE_SHIFT; // // Set initial PRCB, Thread and Process on the last PDR page // Base = (PVOID)((ULONG)Base + 2 * 1024 * 1024); - ArmLoaderBlock.Prcb = KSEG0_BASE | (ULONG)Base; - ArmLoaderBlock.Process = ArmLoaderBlock.Prcb + sizeof(KPRCB); - ArmLoaderBlock.Thread = ArmLoaderBlock.Process + sizeof(EPROCESS); + ArmLoaderBlock->Prcb = KSEG0_BASE | (ULONG)Base; + ArmLoaderBlock->Process = ArmLoaderBlock->Prcb + sizeof(KPRCB); + ArmLoaderBlock->Thread = ArmLoaderBlock->Process + sizeof(EPROCESS); } VOID diff --git a/reactos/ntoskrnl/include/internal/arm/mm.h b/reactos/ntoskrnl/include/internal/arm/mm.h index 983c01263ab..6e4698174da 100644 --- a/reactos/ntoskrnl/include/internal/arm/mm.h +++ b/reactos/ntoskrnl/include/internal/arm/mm.h @@ -5,7 +5,23 @@ #pragma GCC system_header #endif -#define TTB_SHIFT 20 +// +// Number of bits corresponding to the area that a PDE entry represents (1MB) +// +#define PDE_SHIFT 20 +#define PDE_SIZE (1 << PDE_SHIFT) + +// +// Number of bits corresponding to the area that a coarse page table entry represents (4KB) +// +#define PTE_SHIFT 12 +#define PAGE_SIZE (1 << PTE_SHIFT) + +// +// Number of bits corresponding to the area that a coarse page table occupies (1KB) +// +#define CPT_SHIFT 10 +#define CPT_SIZE (1 << CPT_SHIFT) typedef union _ARM_PTE { @@ -19,9 +35,10 @@ typedef union _ARM_PTE struct { ULONG Type:2; - ULONG Reserved:3; + ULONG Ignored:2; + ULONG Reserved:1; ULONG Domain:4; - ULONG Ignored:1; + ULONG Ignored1:1; ULONG BaseAddress:22; } Coarse; struct @@ -93,6 +110,11 @@ typedef struct _ARM_TRANSLATION_TABLE ARM_PTE Pte[4096]; } ARM_TRANSLATION_TABLE, *PARM_TRANSLATION_TABLE; +typedef struct _ARM_COARSE_PAGE_TABLE +{ + ARM_PTE Pte[256]; +} ARM_COARSE_PAGE_TABLE, *PARM_COARSE_PAGE_TABLE; + typedef enum _ARM_L1_PTE_TYPE { FaultPte, @@ -101,6 +123,13 @@ typedef enum _ARM_L1_PTE_TYPE FinePte } ARM_L1_PTE_TYPE; +typedef enum _ARM_L2_PTE_TYPE +{ + LargePte = 1, + SmallPte, + TinyPte +} ARM_L2_PTE_TYPE; + typedef enum _ARM_PTE_ACCESS { FaultAccess, diff --git a/reactos/ntoskrnl/ke/arm/cpu.c b/reactos/ntoskrnl/ke/arm/cpu.c index 03353a6a313..4e59a5c38d2 100644 --- a/reactos/ntoskrnl/ke/arm/cpu.c +++ b/reactos/ntoskrnl/ke/arm/cpu.c @@ -40,7 +40,7 @@ KeFillFixedEntryTb(IN ARM_PTE Pte, PARM_TRANSLATION_TABLE TranslationTable; // - // Hack for 1MB Section Entries + // Fixed TB entries must be section entries // Virtual = (PVOID)((ULONG)Virtual & 0xFFF00000); @@ -69,7 +69,7 @@ KeFillFixedEntryTb(IN ARM_PTE Pte, // Map the PTE for this virtual address // TranslationTable = (PVOID)KeArmTranslationTableRegisterGet().AsUlong; - TranslationTable->Pte[(ULONG)Virtual >> TTB_SHIFT] = Pte; + TranslationTable->Pte[(ULONG)Virtual >> PDE_SHIFT] = Pte; // // Now force a miss @@ -103,7 +103,7 @@ KeFillFixedEntryTb(IN ARM_PTE Pte, // // Clear the PTE // - TranslationTable->Pte[(ULONG)Virtual >> TTB_SHIFT].AsUlong = 0; + TranslationTable->Pte[(ULONG)Virtual >> PDE_SHIFT].AsUlong = 0; } } diff --git a/reactos/ntoskrnl/ke/arm/kiinit.c b/reactos/ntoskrnl/ke/arm/kiinit.c index 8e91e712c02..a1985b1db0c 100644 --- a/reactos/ntoskrnl/ke/arm/kiinit.c +++ b/reactos/ntoskrnl/ke/arm/kiinit.c @@ -20,10 +20,6 @@ ULONG KeNumberProcessIds; ULONG KeNumberTbEntries; #define __ARMV6__ KeIsArmV6 -// -// METAFIXME: We need to stop using 1MB Section Entry TTEs! -// - /* FUNCTIONS ******************************************************************/ VOID