- Share some more inline functions between the kernel and freeldr

- Use __ltr instead of Ke386SetTr
- refactor KiInitializeTss
- Update some Mm conatnts
- Halfplement KeFlushEntireTb
- Clean the mapping of page 0 in KiSystemStartup, as long as we don't clean mappings in freeldr
- Fix a serious bug in KiPageFault, where ebp was used instead of rbp, resulting in recursive page faults as soon as usermode mappings were cleared
- Refactor MmArmInitSystem and related. Pahse 0 initialisation completes here now. we fail later in freelist setup code, which is not 64 bit safe.

svn path=/branches/ros-amd64-bringup/; revision=44144
This commit is contained in:
Timo Kreuzer
2009-11-13 23:30:44 +00:00
parent bb7f766eff
commit dd9ed9ea92
9 changed files with 381 additions and 285 deletions
@@ -58,28 +58,6 @@ typedef struct _PAGE_DIRECTORY_AMD64
HARDWARE_PTE Pde[512];
} PAGE_DIRECTORY_AMD64, *PPAGE_DIRECTORY_AMD64;
PKGDTENTRY64
FORCEINLINE
KiGetGdtEntry(PVOID pGdt, USHORT Index)
{
return (PKGDTENTRY64)((ULONG64)pGdt + (Index & ~RPL_MASK));
}
VOID
FORCEINLINE
KiInitGdtEntry(PKGDTENTRY64 Entry, ULONG64 Base, ULONG Limit, UCHAR Type, UCHAR Dpl)
{
Entry->Bits.Type = Type;
Entry->Bits.Present = 1;
Entry->Bits.Dpl = Dpl;
Entry->BaseLow = (USHORT)(Base & 0xFFFF);
Entry->Bytes.BaseMiddle = (UCHAR)(Base >> 16);
Entry->Bytes.BaseHigh = (UCHAR)(Base >> 24);
Entry->BaseUpper = (ULONG)(Base >> 32);
Entry->LimitLow = (USHORT)(Limit & 0xFFFF);
Entry->Bits.LimitHigh = (ULONG)((Limit >> 16) & 0xf);
Entry->MustBeZero = 0;
}
VOID FrLdrSetupGdtIdt();
@@ -354,8 +354,8 @@ WinLdrSetProcessorContext(PVOID GdtIdt, IN ULONG64 Pcr, IN ULONG64 Tss)
Ke386SetGs(KGDT_64_DATA | RPL_MASK); // 0x2b
Ke386SetSs(KGDT_64_R0_SS); // 0x18
// Load TSR
Ke386SetTr(KGDT_TSS);
/* Load TSR */
__ltr(KGDT_TSS);
DPRINTM(DPRINT_WINDOWS, "leave WinLdrSetProcessorContext\n");
}
@@ -9,6 +9,57 @@
#define KeSetCurrentIrql(x) __writecr8(x)
PKGDTENTRY64
FORCEINLINE
KiGetGdtEntry(PVOID pGdt, USHORT Selector)
{
return (PKGDTENTRY64)((ULONG64)pGdt + (Selector & ~RPL_MASK));
}
PVOID
FORCEINLINE
KiGetGdtDescriptorBase(PKGDTENTRY Entry)
{
return (PVOID)((ULONG64)Entry->BaseLow |
(ULONG64)Entry->Bytes.BaseMiddle << 16 |
(ULONG64)Entry->Bytes.BaseHigh << 24 |
(ULONG64)Entry->BaseUpper << 32);
}
VOID
FORCEINLINE
KiSetGdtDescriptorBase(PKGDTENTRY Entry, ULONG64 Base)
{
Entry->BaseLow = Base & 0xffff;
Entry->Bits.BaseMiddle = (Base >> 16) & 0xff;
Entry->Bits.BaseHigh = (Base >> 24) & 0xff;
Entry->BaseUpper = Base >> 32;
}
PVOID
FORCEINLINE
KiSetGdtDescriptorLimit(PKGDTENTRY Entry, ULONG Limit)
{
Entry->LimitLow = Limit & 0xffff;
Entry->Bits.LimitHigh = Limit >> 16;
}
VOID
FORCEINLINE
KiInitGdtEntry(PKGDTENTRY64 Entry, ULONG64 Base, ULONG Size, UCHAR Type, UCHAR Dpl)
{
KiSetGdtDescriptorBase(Entry, Base);
KiSetGdtDescriptorLimit(Entry, Size - 1);
Entry->Bits.Type = Type;
Entry->Bits.Dpl = Dpl;
Entry->Bits.Present = 1;
Entry->Bits.System = 0;
Entry->Bits.LongMode = 0;
Entry->Bits.DefaultBig = 0;
Entry->Bits.Granularity = 0;
Entry->MustBeZero = 0;
}
#if defined(__GNUC__)
static __inline__ __attribute__((always_inline)) void __lgdt(void *Source)
@@ -41,9 +92,9 @@ static __inline__ __attribute__((always_inline)) void __stmxcsr(unsigned long *D
__asm__ __volatile__("stmxcsr %0" : : "m"(*Destination) : "memory");
}
static __inline__ __attribute__((always_inline)) void __ltr(unsigned short *Source)
static __inline__ __attribute__((always_inline)) void __ltr(unsigned short Source)
{
__asm__ __volatile__("ltr %0" : : "m"(*Source));
__asm__ __volatile__("ltr %0" : : "rm"(Source));
}
static __inline__ __attribute__((always_inline)) void __str(unsigned short *Destination)
@@ -51,25 +102,6 @@ static __inline__ __attribute__((always_inline)) void __str(unsigned short *Dest
__asm__ __volatile__("str %0" : : "m"(*Destination) : "memory");
}
#define Ke386GetLocalDescriptorTable(X) \
__asm__("sldt %0\n\t" \
: /* no outputs */ \
: "m" (X));
#define Ke386SetLocalDescriptorTable(X) \
__asm__("lldt %w0\n\t" \
: /* no outputs */ \
: "q" (X));
#define Ke386SetTr(X) __asm__ __volatile__("ltr %%ax" : :"a" (X));
#define Ke386GetTr(X) \
__asm__("str %0\n\t" \
: /* no outputs */ \
: "m" (X));
#define Ke386SaveFlags(x) __asm__ __volatile__("pushfq ; popq %0":"=rm" (x): /* no input */)
#define Ke386RestoreFlags(x) __asm__ __volatile__("pushq %0 ; popfq": /* no output */ :"irm" (x):"memory")
#define _Ke386GetSeg(N) ({ \
unsigned int __d; \
+3 -12
View File
@@ -46,6 +46,8 @@
#define X86_MSR_CSTAR 0xC0000083
#define X86_MSR_SFMASK 0xC0000084
#define AMD64_TSS 9
#ifndef __ASM__
#include "intrin_i.h"
@@ -118,21 +120,10 @@ KeInvalidateTlbEntry(IN PVOID Address)
}
struct _KPCR;
VOID
KiInitializeGdt(struct _KPCR* Pcr);
VOID
Ki386ApplicationProcessorInitializeTSS(VOID);
// Hack
VOID KiRosPrepareForSystemStartup(ULONG, PROS_LOADER_PARAMETER_BLOCK);
VOID
FASTCALL
Ki386InitializeTss(
IN PKTSS Tss,
IN PVOID GdtBase,
IN UINT64 Stack
);
KiInitializeTss(IN PKTSS Tss, IN UINT64 Stack);
VOID KiDivideErrorFault();
VOID KiDebugTrapOrFault();
+17 -7
View File
@@ -5,11 +5,24 @@
#ifndef __NTOSKRNL_INCLUDE_INTERNAL_AMD64_MM_H
#define __NTOSKRNL_INCLUDE_INTERNAL_AMD64_MM_H
/* Helper macros */
#define PAGE_MASK(x) ((x)&(~0xfff))
#define PAE_PAGE_MASK(x) ((x)&(~0xfffLL))
#define HYPER_SPACE 0xFFFFF70000000000ULL
#define HYPER_SPACE_END 0xFFFFF77FFFFFFFFFULL
/* Memory layout base addresses */
#define HYPER_SPACE 0xFFFFF70000000000ULL
#define HYPER_SPACE_END 0xFFFFF77FFFFFFFFFULL
#define MI_SESSION_VIEW_END (PVOID)0xFFFFF97FFF000000ULL
#define MI_SESSION_SPACE_END (PVOID)0xFFFFF98000000000ULL
#define MI_PAGED_POOL_START (PVOID)0xFFFFFA8000000000ULL
#define MI_NON_PAGED_SYSTEM_START_MIN 0xFFFFFAA000000000ULL
#define MI_NONPAGED_POOL_END (PVOID)0xFFFFFAE000000000ULL
#define MI_DEBUG_MAPPING (PVOID)0xFFFFFFFF80000000ULL // FIXME
PULONG64
FORCEINLINE
@@ -87,8 +100,8 @@ MiAddressToPte(PVOID Address)
#define MI_MIN_PAGES_FOR_NONPAGED_POOL_TUNING ((255*1024*1024) >> PAGE_SHIFT)
#define MI_MIN_PAGES_FOR_SYSPTE_TUNING ((19*1024*1024) >> PAGE_SHIFT)
#define MI_MIN_PAGES_FOR_SYSPTE_BOOST ((32*1024*1024) >> PAGE_SHIFT)
#define MI_MAX_INIT_NONPAGED_POOL_SIZE (128 * 1024 * 1024)
#define MI_MAX_NONPAGED_POOL_SIZE (128 * 1024 * 1024)
#define MI_MAX_INIT_NONPAGED_POOL_SIZE (128ULL * 1024 * 1024 * 1024)
#define MI_MAX_NONPAGED_POOL_SIZE (128ULL * 1024 * 1024 * 1024)
#define MI_MAX_FREE_PAGE_LISTS 4
#define MI_MIN_INIT_PAGED_POOLSIZE (32 * 1024 * 1024)
@@ -104,9 +117,6 @@ MiAddressToPte(PVOID Address)
#define MI_SYSTEM_VIEW_SIZE (16 * 1024 * 1024)
#define MI_PAGED_POOL_START (PVOID)0xFFFFFA8000000000ULL
#define MI_NONPAGED_POOL_END (PVOID)0xFFFFFAE000000000ULL
#define MI_DEBUG_MAPPING (PVOID)0xFFFFFFFF80000000ULL // FIXME
#define MM_HIGHEST_VAD_ADDRESS \
(PVOID)((ULONG_PTR)MM_HIGHEST_USER_ADDRESS - (16 * PAGE_SIZE))
+26 -28
View File
@@ -46,6 +46,9 @@ BOOLEAN KiSMTProcessorsPresent;
KIRQL KiOldIrql;
ULONG KiFreezeFlag;
/* Flush data */
volatile LONG KiTbFlushTimeStamp;
/* CPU Signatures */
static const CHAR CmpIntelID[] = "GenuineIntel";
static const CHAR CmpAmdID[] = "AuthenticAMD";
@@ -90,7 +93,7 @@ KiSetProcessorType(VOID)
KeGetCurrentPrcb()->CpuID = 0;
/* Save EFlags */
Ke386SaveFlags(EFlags);
EFlags = __readeflags();
/* Do CPUID 1 now */
__cpuid(Reg, 1);
@@ -115,7 +118,7 @@ KiSetProcessorType(VOID)
KeGetCurrentPrcb()->CpuStep = (USHORT)Stepping;
/* Restore EFLAGS */
Ke386RestoreFlags(EFlags);
__writeeflags(EFlags);
}
ULONG
@@ -389,35 +392,19 @@ KiGetCacheInformation(VOID)
VOID
FASTCALL
Ki386InitializeTss(IN PKTSS64 Tss,
IN PVOID GdtBase,
IN UINT64 Stack)
KiInitializeTss(IN PKTSS64 Tss,
IN UINT64 Stack)
{
PKGDTENTRY64 TssEntry;
/* Initialize the TSS descriptor entry */
TssEntry = (PVOID)((ULONG64)GdtBase + KGDT_TSS);
TssEntry->Bits.Type = 9;//AMD64_TSS;
TssEntry->Bits.Dpl = 0;
TssEntry->Bits.Present = 1;
TssEntry->Bits.System = 0;
TssEntry->Bits.LongMode = 0;
TssEntry->Bits.DefaultBig = 0;
TssEntry->Bits.Granularity = 0;
TssEntry->MustBeZero = 0;
/* Get pointer to the GDT entry */
TssEntry = KiGetGdtEntry(KeGetPcr()->GdtBase, KGDT_TSS);
/* Descriptor base is the TSS address */
TssEntry->BaseLow = (ULONG64)Tss & 0xffff;
TssEntry->Bits.BaseMiddle = ((ULONG64)Tss >> 16) & 0xff;
TssEntry->Bits.BaseHigh = ((ULONG64)Tss >> 24) & 0xff;
TssEntry->BaseUpper = (ULONG64)Tss >> 32;
/* Set the limit */
TssEntry->LimitLow = sizeof(KTSS64) -1;
TssEntry->Bits.LimitHigh = 0;
/* Initialize the GDT entry */
KiInitGdtEntry(TssEntry, (ULONG64)Tss, sizeof(KTSS64), AMD64_TSS, 0);
/* Zero out the TSS */
RtlZeroMemory(Tss, sizeof(KTSS));
RtlZeroMemory(Tss, sizeof(KTSS64));
/* FIXME: I/O Map? */
Tss->IoMapBase = 0x68;
@@ -435,8 +422,7 @@ Ki386InitializeTss(IN PKTSS64 Tss,
Tss->Ist[3] = (ULONG64)KiDoubleFaultStack;
/* Load the task register */
Ke386SetTr(KGDT_TSS);
__ltr(KGDT_TSS);
}
VOID
@@ -535,7 +521,19 @@ NTAPI
KeFlushEntireTb(IN BOOLEAN Invalid,
IN BOOLEAN AllProcessors)
{
UNIMPLEMENTED;
KIRQL OldIrql;
// FIXME: halfplemented
/* Raise the IRQL for the TB Flush */
OldIrql = KeRaiseIrqlToSynchLevel();
/* Flush the TB for the Current CPU, and update the flush stamp */
KeFlushCurrentTb();
/* Update the flush stamp and return to original IRQL */
InterlockedExchangeAdd(&KiTbFlushTimeStamp, 1);
KeLowerIrql(OldIrql);
}
KAFFINITY
+14 -14
View File
@@ -337,7 +337,7 @@ KiInitializePcr(IN PKIPCR Pcr,
IN PVOID DpcStack)
{
KDESCRIPTOR GdtDescriptor = {{0},0,0}, IdtDescriptor = {{0},0,0};
KGDTENTRY64 TssSelector;
PKGDTENTRY64 TssEntry;
USHORT Tr = 0;
/* Zero out the PCR */
@@ -375,19 +375,16 @@ KiInitializePcr(IN PKIPCR Pcr,
Pcr->IdtBase = (PKIDTENTRY)IdtDescriptor.Base;
/* Get TSS Selector */
Ke386GetTr(Tr); // <- FIXME: this is ugly!
if (Tr != KGDT_TSS) Tr = KGDT_TSS; // FIXME: HACKHACK
__str(&Tr);
ASSERT(Tr == KGDT_TSS);
/* Get TSS Selector, mask it and get its GDT Entry */
TssSelector = *(PKGDTENTRY)((ULONG_PTR)Pcr->GdtBase + (Tr & ~RPL_MASK));
/* Get TSS Entry */
TssEntry = KiGetGdtEntry(Pcr->GdtBase, Tr);
/* Get the KTSS itself */
Pcr->TssBase = (PKTSS)(ULONG_PTR)(TssSelector.BaseLow |
TssSelector.Bytes.BaseMiddle << 16 |
TssSelector.Bytes.BaseHigh << 24 |
(ULONG64)TssSelector.BaseUpper << 32);
Pcr->TssBase = KiGetGdtDescriptorBase(TssEntry);
Pcr->Prcb.RspBase = Pcr->TssBase->Rsp0;
Pcr->Prcb.RspBase = Pcr->TssBase->Rsp0; // FIXME
/* Set DPC Stack */
Pcr->Prcb.DpcStack = DpcStack;
@@ -403,7 +400,7 @@ KiInitializePcr(IN PKIPCR Pcr,
Pcr->Prcb.CurrentThread = IdleThread;
/* Start us out at PASSIVE_LEVEL */
// Pcr->Irql = PASSIVE_LEVEL;
Pcr->Irql = PASSIVE_LEVEL;
KeSetCurrentIrql(PASSIVE_LEVEL);
}
@@ -627,6 +624,9 @@ KiSystemStartup(IN ULONG_PTR Dummy,
FrLdrDbgPrint = ((PLOADER_PARAMETER_BLOCK)Dummy)->u.I386.CommonDataArea;
FrLdrDbgPrint("Hello from KiSystemStartup!!!\n");
/* HACK, because freeldr maps page 0 */
MiAddressToPte((PVOID)0)->u.Hard.Valid = 0;
KiSystemStartupReal((PLOADER_PARAMETER_BLOCK)Dummy);
// KiRosPrepareForSystemStartup(Dummy, LoaderBlock);
@@ -699,7 +699,7 @@ KiSystemStartupReal(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
if (Cpu == 0)
{
/* Setup the TSS descriptors and entries */
Ki386InitializeTss(Pcr->TssBase, Pcr->GdtBase, InitialStack);
KiInitializeTss(Pcr->TssBase, InitialStack);
/* Setup the IDT */
KeInitExceptions();
@@ -711,7 +711,7 @@ KiSystemStartupReal(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
KdInitSystem(0, KeLoaderBlock);
/* Check for break-in */
// if (KdPollBreakIn()) DbgBreakPointWithStatus(1);
if (KdPollBreakIn()) DbgBreakPointWithStatus(DBG_STATUS_CONTROL_C);
/* Hack! Wait for the debugger! */
while (!KdPollBreakIn());
@@ -728,7 +728,7 @@ KiSystemStartupReal(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
// DPRINT1("Gdt = %p, Idt = %p, Pcr = %p, Tss = %p\n", Gdt, Idt, Pcr, Tss);
DbgBreakPointWithStatus(0);
DbgBreakPointWithStatus(DBG_STATUS_CONTROL_C);
/* Initialize the Processor with HAL */
HalInitializeProcessor(Cpu, KeLoaderBlock);
+15 -13
View File
@@ -19,7 +19,7 @@ _MsgUnimplemented:
.asciz "WARNING: %s at %s:%d is UNIMPLEMENTED!\n"
_MsgPageFault:
.ascii "Page fault 0x%x at %p!\n\0"
.ascii "Page fault! Code = 0x%x, RIP = %p, FaultingAddress = %p\n\0"
_MsgGeneralProtFault:
.ascii "General protection fault at %p!\n\0"
@@ -333,9 +333,9 @@ KiDebugTrapOrFaultKMode:
ENTER_TRAP_FRAME (0x28), TRAPFLAG_ALL
lea rcx, _MsgBreakpointTrap[rip]
mov rdx, rbp
call _FrLdrDbgPrint[rip]
// lea rcx, _MsgBreakpointTrap[rip]
// mov rdx, rsp
// call _FrLdrDbgPrint[rip]
/* Dispatch the exception */
mov ecx, STATUS_BREAKPOINT
@@ -495,23 +495,25 @@ KiDebugTrapOrFaultKMode:
.pushframe 1
/* We have an error code */
// lea rcx, _MsgPageFault[rip]
// mov rdx, [rsp]
// mov r8, [rsp+8]
// mov r9, rsp
// call _FrLdrDbgPrint[rip]
ENTER_TRAP_FRAME (0x28), TRAPFLAG_ALL
#if 0
lea rcx, _MsgPageFault[rip]
mov rdx, [rbp + KTRAP_FRAME_ErrorCode]
mov r8, [rbp + KTRAP_FRAME_Rip]
mov r9, [rbp + KTRAP_FRAME_FaultAddress]
call _FrLdrDbgPrint[rip]
#endif
/* Save page fault address */
mov rdx, cr2
mov [rbp + KTRAP_FRAME_FaultAddress], rdx
/* Call page fault handler */
mov ecx, [ebp + KTRAP_FRAME_ErrorCode] // StoreInstruction
mov ecx, [rbp + KTRAP_FRAME_ErrorCode] // StoreInstruction
and ecx, 1
// rdx == Address
mov r8b, [ebp + KTRAP_FRAME_SegCs] // Mode
mov r8b, [rbp + KTRAP_FRAME_SegCs] // Mode
and r8b, 1
mov r9, rbp // TrapInformation
// call _MmAccessFault
@@ -524,7 +526,7 @@ KiDebugTrapOrFaultKMode:
jge PageFaultReturn
/* Set parameter 1 to error code */
mov r9d, [ebp + KTRAP_FRAME_ErrorCode]
mov r9d, [rbp + KTRAP_FRAME_ErrorCode]
/* Set parameter2 to faulting address */
mov r10, cr2 // Param2 = faulting address
+251 -166
View File
@@ -15,9 +15,7 @@
#include "../ARM3/miarm.h"
#define MI_SESSION_SPACE_END (PVOID)0xFFFFF98000000000ULL
#define MI_SESSION_VIEW_END 0xFFFFF97FFF000000ULL
#define MI_NON_PAGED_SYSTEM_START_MIN 0x0FFFFFAA000000000ULL
extern PMMPTE MmDebugPte;
/* GLOBALS *****************************************************************/
@@ -65,10 +63,11 @@ PVOID MmPagedPoolEnd;
ULONG64 MmBootImageSize;
PPHYSICAL_MEMORY_DESCRIPTOR MmPhysicalMemoryBlock;
RTL_BITMAP MiPfnBitMap;
ULONG MmNumberOfPhysicalPages, MmHighestPhysicalPage, MmLowestPhysicalPage = -1;
ULONG MmNumberOfPhysicalPages, MmHighestPhysicalPage, MmLowestPhysicalPage = -1; // FIXME: ULONG64
ULONG64 MmNumberOfSystemPtes;
PMMPTE MmSystemPagePtes;
ULONG64 MxPfnAllocation;
ULONG64 MxPfnSizeInBytes;
PVOID MmSystemCacheStart;
PVOID MmSystemCacheEnd;
@@ -83,24 +82,59 @@ MEMORY_ALLOCATION_DESCRIPTOR MxOldFreeDescriptor;
PFN_NUMBER MxFreePageBase;
ULONG64 MxFreePageCount = 0;
ULONG
NoDbgPrint(const char *Format, ...)
{
return 0;
}
VOID
NTAPI
MxSetupFreePageList(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
MiEvaluateMemoryDescriptors(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
{
PMEMORY_ALLOCATION_DESCRIPTOR MdBlock;
PLIST_ENTRY ListEntry;
PFN_NUMBER LastPage;
/* Loop the memory descriptors */
for (ListEntry = LoaderBlock->MemoryDescriptorListHead.Flink;
ListEntry != &LoaderBlock->MemoryDescriptorListHead;
ListEntry = ListEntry->Flink)
{
/* Get the memory block */
/* Get the memory descriptor */
MdBlock = CONTAINING_RECORD(ListEntry,
MEMORY_ALLOCATION_DESCRIPTOR,
ListEntry);
/* Check if this is free memory */
/* Skip pages that are not part of the PFN database */
if ((MdBlock->MemoryType == LoaderFirmwarePermanent) ||
(MdBlock->MemoryType == LoaderBBTMemory) ||
(MdBlock->MemoryType == LoaderHALCachedMemory) ||
(MdBlock->MemoryType == LoaderSpecialMemory) ||
(MdBlock->MemoryType == LoaderBad))
{
continue;
}
/* Add this to the total of pages */
MmNumberOfPhysicalPages += MdBlock->PageCount;
/* Check if this is the new lowest page */
if (MdBlock->BasePage < MmLowestPhysicalPage)
{
/* Update the lowest page */
MmLowestPhysicalPage = MdBlock->BasePage;
}
/* Check if this is the new highest page */
LastPage = MdBlock->BasePage + MdBlock->PageCount - 1;
if (LastPage > MmHighestPhysicalPage)
{
/* Update the highest page */
MmHighestPhysicalPage = LastPage;
}
/* Check if this is currently free memory */
if ((MdBlock->MemoryType == LoaderFree) ||
(MdBlock->MemoryType == LoaderLoadedProgram) ||
(MdBlock->MemoryType == LoaderFirmwareTemporary) ||
@@ -142,14 +176,17 @@ MxGetNextPage(IN PFN_NUMBER PageCount)
return Pfn;
}
VOID
MxMapPage(PVOID Address)
PMMPTE
NTAPI
MxGetPte(PVOID Address)
{
PMMPTE Pte;
MMPTE TmpPte;
/* Setup template pte */
TmpPte.u.Long = 0;
TmpPte.u.Hard.Valid = 1;
TmpPte.u.Flush.Valid = 1;
TmpPte.u.Flush.Write = 1;
/* Get a pointer to the PXE */
Pte = MiAddressToPxe(Address);
@@ -180,163 +217,41 @@ MxMapPage(PVOID Address)
/* Get a pointer to the PTE */
Pte = MiAddressToPte(Address);
if (!Pte->u.Hard.Valid)
{
/* It's not valid, map it! */
TmpPte.u.Hard.PageFrameNumber = MxGetNextPage(1);
*Pte = TmpPte;
}
return Pte;
}
VOID
MxMapPageRange(PVOID Address, ULONG64 PageCount)
{
ULONG64 i;
MMPTE TmpPte, *Pte;
for (i = 0; i < PageCount; i++)
/* Setup template pte */
TmpPte.u.Long = 0;
TmpPte.u.Flush.Valid = 1;
TmpPte.u.Flush.Write = 1;
while (PageCount--)
{
MxMapPage(Address);
/* Get the PTE for that page */
Pte = MxGetPte(Address);
ASSERT(Pte->u.Hard.Valid == 0);
/* Map a physical page */
TmpPte.u.Hard.PageFrameNumber = MxGetNextPage(1);
*Pte = TmpPte;
/* Goto next page */
Address = (PVOID)((ULONG64)Address + PAGE_SIZE);
}
}
VOID
NTAPI
MiArmIninializeMemoryLayout(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
MiArmConfigureMemorySizes(IN PLOADER_PARAMETER_BLOCK LoaderBloc)
{
/* Get the size of the boot loader's image allocations */
MmBootImageSize = KeLoaderBlock->Extension->LoaderPagesSpanned;
MmBootImageSize *= PAGE_SIZE;
MmBootImageSize = (MmBootImageSize + (4 * 1024 * 1024) - 1) & ~((4 * 1024 * 1024) - 1);
ASSERT((MmBootImageSize % (4 * 1024 * 1024)) == 0);
MiSessionSpaceEnd = (PVOID)MI_SESSION_SPACE_END;
/* This is where we will load Win32k.sys and the video driver */
MiSessionImageEnd = MiSessionSpaceEnd;
MiSessionImageStart = (PVOID)((ULONG_PTR)MiSessionImageEnd -
MmSessionImageSize);
/* The view starts right below the session working set (itself below
* the image area) */
MiSessionViewEnd = (PVOID)MI_SESSION_VIEW_END;
MiSessionViewStart = (PVOID)((ULONG_PTR)MiSessionViewStart -
MmSessionViewSize);
/* Session pool follows */
MiSessionPoolEnd = MiSessionViewStart;
MiSessionPoolStart = (PVOID)((ULONG_PTR)MiSessionPoolEnd -
MmSessionPoolSize);
/* And it all begins here */
MmSessionBase = MiSessionPoolStart;
// Sanity check that our math is correct
//ASSERT((ULONG_PTR)MmSessionBase + MmSessionSize == PTE_BASE);
/* System view space ends at session space, so now that we know where
* this is, we can compute the base address of system view space itself. */
MiSystemViewStart = (PVOID)((ULONG_PTR)MmSessionBase -
MmSystemViewSize);
/* Use the default */
MmNumberOfSystemPtes = 22000;
/* FIXME: should start below paged pool */
MmPfnDatabase = (PVOID)0xFFFFFD5FC0000000ULL;
}
VOID
MiArmInitializePageTable()
{
ULONG64 PageFrameOffset;
PMMPTE StartPte, EndPte;
/* Set CR3 for the system process */
PageFrameOffset = ((PMMPTE)PXE_BASE)->u.Hard.PageFrameNumber << PAGE_SHIFT;
PsGetCurrentProcess()->Pcb.DirectoryTableBase[0] = PageFrameOffset;
/* Clear user mode mappings in PML4 */
StartPte = MiAddressToPxe(0);
EndPte = MiAddressToPxe(MmSystemRangeStart);
RtlZeroMemory(StartPte, (EndPte - StartPte) * sizeof(MMPTE));
}
VOID
NTAPI
MiArmEvaluateMemoryDescriptors(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
{
PMEMORY_ALLOCATION_DESCRIPTOR MdBlock;
PLIST_ENTRY ListEntry;
PFN_NUMBER BasePage, LastPage, PageCount;
/* Loop the memory descriptors */
for (ListEntry = LoaderBlock->MemoryDescriptorListHead.Flink;
ListEntry != &LoaderBlock->MemoryDescriptorListHead;
ListEntry = ListEntry->Flink)
{
/* Get the descriptor */
MdBlock = CONTAINING_RECORD(ListEntry,
MEMORY_ALLOCATION_DESCRIPTOR,
ListEntry);
/* Skip pages that are not part of the PFN database */
if ((MdBlock->MemoryType == LoaderFirmwarePermanent) ||
(MdBlock->MemoryType == LoaderBBTMemory) ||
(MdBlock->MemoryType == LoaderHALCachedMemory) || // ???
(MdBlock->MemoryType == LoaderSpecialMemory))
{
continue;
}
/* Check if BURNMEM was used */
if (MdBlock->MemoryType != LoaderBad)
{
/* Count this in the total of pages */
MmNumberOfPhysicalPages += MdBlock->PageCount;
}
BasePage = MdBlock->BasePage;
LastPage = MdBlock->BasePage + MdBlock->PageCount - 1;
/* Check if this is the new lowest page */
if (BasePage < MmLowestPhysicalPage)
{
/* Update the lowest page */
MmLowestPhysicalPage = BasePage;
}
/* Check if this is the new highest page */
if (LastPage > MmHighestPhysicalPage)
{
/* Update the highest page */
MmHighestPhysicalPage = LastPage;
}
DPRINT1("BasePage = %ld, LastPage = %ld\n", BasePage, LastPage);
__debugbreak();
/* Map pages for the PFN database */
PageCount = PAGE_ROUND_UP(MdBlock->PageCount * sizeof(MMPFN)) / PAGE_SIZE;
MxMapPageRange(&MmPfnDatabase[BasePage], PageCount);
/* Zero out the pages */
RtlZeroMemory(&MmPfnDatabase[BasePage], PageCount * PAGE_SIZE);
}
/* Calculate the number of bytes, and then convert to pages */
MxPfnAllocation = (MmHighestPhysicalPage + 1) * sizeof(MMPFN);
MxPfnAllocation >>= PAGE_SHIFT;
MxPfnAllocation++;
}
VOID
NTAPI
MiArmPrepareNonPagedPool()
{
PFN_NUMBER PageCount;
MmBootImageSize = KeLoaderBlock->Extension->LoaderPagesSpanned * PAGE_SIZE;
MmBootImageSize = ROUND_UP(MmBootImageSize, 4 * 1024 * 1024);
/* Check if this is a machine with less than 256MB of RAM, and no overide */
if ((MmNumberOfPhysicalPages <= MI_MIN_PAGES_FOR_NONPAGED_POOL_TUNING) &&
@@ -396,15 +311,174 @@ MiArmPrepareNonPagedPool()
MmMaximumNonPagedPoolInBytes = MI_MAX_NONPAGED_POOL_SIZE;
}
// MmSessionImageSize
}
VOID
NTAPI
MiArmInitializeMemoryLayout(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
{
/* Set up session space */
MiSessionSpaceEnd = (PVOID)MI_SESSION_SPACE_END;
/* This is where we will load Win32k.sys and the video driver */
MiSessionImageEnd = MiSessionSpaceEnd;
MiSessionImageStart = (PVOID)((ULONG_PTR)MiSessionImageEnd -
MmSessionImageSize);
/* The view starts right below the session working set (itself below
* the image area) */
MiSessionViewEnd = MI_SESSION_VIEW_END;
MiSessionViewStart = (PVOID)((ULONG_PTR)MiSessionViewStart -
MmSessionViewSize);
/* Session pool follows */
MiSessionPoolEnd = MiSessionViewStart;
MiSessionPoolStart = (PVOID)((ULONG_PTR)MiSessionPoolEnd -
MmSessionPoolSize);
/* And it all begins here */
MmSessionBase = MiSessionPoolStart;
/* System view space ends at session space, so now that we know where
* this is, we can compute the base address of system view space itself. */
MiSystemViewStart = (PVOID)((ULONG_PTR)MmSessionBase -
MmSystemViewSize);
/* Use the default */
MmNumberOfSystemPtes = 22000;
ASSERT(MiSessionViewEnd <= MiSessionImageStart);
ASSERT(MmSessionBase <= MiSessionPoolStart);
}
VOID
MiArmInitializePageTable()
{
ULONG64 PageFrameOffset;
PMMPTE Pte, StartPte, EndPte;
/* Get current directory base */
PageFrameOffset = ((PMMPTE)PXE_SELFMAP)->u.Hard.PageFrameNumber << PAGE_SHIFT;
ASSERT(PageFrameOffset == __readcr3());
/* Set directory base for the system process */
PsGetCurrentProcess()->Pcb.DirectoryTableBase[0] = PageFrameOffset;
/* HACK: don't use freeldr debug pront anymore */
FrLdrDbgPrint = NoDbgPrint;
#if 1
/* Clear user mode mappings in PML4 */
StartPte = MiAddressToPxe(0);
EndPte = MiAddressToPxe(MmHighestUserAddress);
for (Pte = StartPte; Pte <= EndPte; Pte++)
{
/* Zero the pte */
Pte->u.Long = 0;
}
#else
/* Clear user mode mappings in PML4 */
StartPte = MiAddressToPte(0);
EndPte = MiAddressToPte((PVOID)0xa00000);
for (Pte = StartPte; Pte < EndPte; Pte++)
{
/* Zero the pte */
//Pte->u.Long = 0;
}
/* Flush the TLB */
KeFlushCurrentTb();
// MiAddressToPde(0)->u.Long = 0;
// MiAddressToPde((PVOID)0x200000)->u.Long = 0;
// MiAddressToPde((PVOID)0x400000)->u.Long = 0;
// MiAddressToPde((PVOID)0x600000)->u.Long = 0;
// MiAddressToPde((PVOID)0x800000)->u.Long = 0;
// MiAddressToPpe->u.Long = 0;
#endif
/* Flush the TLB */
KeFlushCurrentTb();
/* Setup debug mapping pte */
MmDebugPte = MxGetPte(MI_DEBUG_MAPPING);
}
VOID
NTAPI
MiArmPreparePfnDatabse(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
{
PMEMORY_ALLOCATION_DESCRIPTOR MdBlock;
PLIST_ENTRY ListEntry;
PFN_COUNT PageCount;
PVOID PageBase;
/* The PFN database is at the start of the non paged region */
MmPfnDatabase = (PVOID)((ULONG64)MmNonPagedPoolEnd - MmMaximumNonPagedPoolInBytes);
/* Loop the memory descriptors */
for (ListEntry = LoaderBlock->MemoryDescriptorListHead.Flink;
ListEntry != &LoaderBlock->MemoryDescriptorListHead;
ListEntry = ListEntry->Flink)
{
/* Get the memory descriptor */
MdBlock = CONTAINING_RECORD(ListEntry,
MEMORY_ALLOCATION_DESCRIPTOR,
ListEntry);
/* Skip pages that are not part of the PFN database */
if ((MdBlock->MemoryType == LoaderFirmwarePermanent) ||
(MdBlock->MemoryType == LoaderBBTMemory) ||
(MdBlock->MemoryType == LoaderHALCachedMemory) ||
(MdBlock->MemoryType == LoaderSpecialMemory) ||
(MdBlock->MemoryType != LoaderBad))
{
continue;
}
/* Map pages for the PFN database */
PageCount = ROUND_TO_PAGES(MdBlock->PageCount * sizeof(MMPFN)) / PAGE_SIZE;
PageBase = PAGE_ALIGN(&MmPfnDatabase[MdBlock->BasePage]);
MxMapPageRange(PageBase, PageCount);
/* Zero out the pages */
RtlZeroMemory(PageBase, PageCount * PAGE_SIZE);
}
/* Calculate the number of bytes, and then convert to pages */
MxPfnSizeInBytes = ROUND_TO_PAGES(MmHighestPhysicalPage + 1) * sizeof(MMPFN);
MxPfnAllocation = MxPfnSizeInBytes >> PAGE_SHIFT;
/* Reduce maximum pool size */
MmMaximumNonPagedPoolInBytes -= MxPfnSizeInBytes;
}
VOID
NTAPI
MiArmPrepareNonPagedPool()
{
PFN_NUMBER PageCount;
PVOID Address;
/* Non paged pool comes after the PFN database */
MmNonPagedPoolStart = (PVOID)((ULONG64)MmPfnDatabase +
MxPfnSizeInBytes);
ASSERT((ULONG64)MmNonPagedPoolEnd == (ULONG64)MmNonPagedPoolStart +
MmMaximumNonPagedPoolInBytes);
/* Calculate the nonpaged pool expansion start region */
MmNonPagedPoolExpansionStart = (PVOID)((ULONG_PTR)MmNonPagedPoolEnd -
MmMaximumNonPagedPoolInBytes +
MmSizeOfNonPagedPoolInBytes);
MmNonPagedPoolExpansionStart = (PVOID)PAGE_ALIGN(MmNonPagedPoolExpansionStart);
DPRINT("NP Pool has been tuned to: %d bytes and %d bytes\n",
MmSizeOfNonPagedPoolInBytes, MmMaximumNonPagedPoolInBytes);
/* Now calculate the nonpaged system VA region, which includes the
* nonpaged pool expansion (above) and the system PTEs. Note that it is
* then aligned to a PDE boundary (4MB). */
@@ -427,15 +501,21 @@ MiArmPrepareNonPagedPool()
ASSERT(MmNumberOfSystemPtes > 1000);
}
/* Non paged pool comes after the PFN database */
MmNonPagedPoolStart = (PVOID)((ULONG_PTR)MmPfnDatabase +
(MxPfnAllocation << PAGE_SHIFT));
/* Map the nonpaged pool */
PageCount = (MmSizeOfNonPagedPoolInBytes + PAGE_SIZE - 1) / PAGE_SIZE;
MxMapPageRange(MmNonPagedPoolStart, PageCount);
/* Sanity check: make sure we have properly defined the system PTE space */
/* Create PTEs for the paged pool extension */
for (Address = MmNonPagedPoolExpansionStart;
Address < MmNonPagedPoolEnd;
Address = (PVOID)((ULONG64)Address + PAGE_SIZE))
{
/* Create PXE, PPE, PDE and set PTE to 0*/
MxGetPte(Address)->u.Long = 0;
}
//DPRINT1("MmNonPagedPoolStart = %p, Pte=%p \n", MmNonPagedPoolStart, MiAddressToPte(MmNonPagedPoolStart));
/* Sanity check */
ASSERT(MiAddressToPte(MmNonPagedSystemStart) <
MiAddressToPte(MmNonPagedPoolExpansionStart));
@@ -448,18 +528,22 @@ MmArmInitSystem(IN ULONG Phase,
{
if (Phase == 0)
{
/* Get a continuous range of physical pages */
MxSetupFreePageList(LoaderBlock);
/* Parse memory descriptors */
MiEvaluateMemoryDescriptors(LoaderBlock);
/* Configure the memory sizes */
MiArmConfigureMemorySizes(LoaderBlock);
/* Initialize the memory layout */
MiArmIninializeMemoryLayout(LoaderBlock);
MiArmInitializeMemoryLayout(LoaderBlock);
/* Loop descriptors and prepare PFN database */
MiArmEvaluateMemoryDescriptors(LoaderBlock);
/* Prepare PFN database mappings */
MiArmPreparePfnDatabse(LoaderBlock);
/* Initialize some mappings */
MiArmInitializePageTable();
/* Configure size of the non paged pool */
/* Prepare paged pool mappings */
MiArmPrepareNonPagedPool();
/* Initialize the ARM3 nonpaged pool */
@@ -476,6 +560,7 @@ MmArmInitSystem(IN ULONG Phase,
/* The PFN database was created, restore the free descriptor */
*MxFreeDescriptor = MxOldFreeDescriptor;
ASSERT(FALSE);
}