Say hello to 4KB pages! Removed bring-up 1MB page hacks all over FreeLDR, and setup the kernel pages the same way the x86 build does it -- 6MB from 0x80800000 to 0x80DFFFFF for kernel and drivers.

We still identity map the bottom 0MB of memory with a 1MB page, since this makes the most sense.
We now map the low 8MB of memory to 0x80000000-0x807FFFFF, also with 4KB pages. This area will be discardable after early-init, and contains the early boot structures allocated by FreeLDR.
The Loader Parameter Block and its Extension are now dynamically allocated, instead of being static inside FreeLDR.
Fixed some bugs in the ARM_PTE structure.

svn path=/trunk/; revision=32350
This commit is contained in:
ReactOS Portable Systems Group 2008-02-14 02:25:25 +00:00
parent 3f38f62b4c
commit 70fbfefbe5
5 changed files with 229 additions and 79 deletions

View file

@ -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

View file

@ -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

View file

@ -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,

View file

@ -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;
}
}

View file

@ -20,10 +20,6 @@ ULONG KeNumberProcessIds;
ULONG KeNumberTbEntries;
#define __ARMV6__ KeIsArmV6
//
// METAFIXME: We need to stop using 1MB Section Entry TTEs!
//
/* FUNCTIONS ******************************************************************/
VOID