Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

283 lines
7.5 KiB

/*++
Module Name:
intimap.c
Abstract:
This module initializes the system process mapping for a 64-bit Alpha
system.
Author:
David N. Cutler (davec) 5-Jan-1998
Environment:
Kernel mode only.
Revision History:
--*/
#include "bldr.h"
#include "arc.h"
//
// Define size of page map.
//
#define PD_INDEX(va) (((va) >> PDI2_SHIFT) & PDI_MASK)
#define PAGE_MAP_SIZE (PD_INDEX(KSEG2_BASE) - PD_INDEX(KSEG0_BASE))
ARC_STATUS
BlInitializeSystemProcessMap (
IN PLOADER_PARAMETER_BLOCK LoaderBlock
)
/*++
Routine Description:
This function initializes the system process map for 64-bit Alpha
systems.
Arguments:
LoaderBlock - Supplies a pointer to the loader parameter block.
Return Value:
None.
--*/
{
ULONG Base;
ULONG Count;
PMEMORY_ALLOCATION_DESCRIPTOR Descriptor;
ULONG Index;
PLIST_ENTRY ListHead;
UCHAR PageMap[PAGE_MAP_SIZE];
PLIST_ENTRY NextEntry;
ULONG Number;
PHARDWARE_PTE Pdr1;
PHARDWARE_PTE Pdr2;
PHARDWARE_PTE Ptp;
ULONG PdrPage;
ARC_STATUS Status;
ULONG Total;
//
// On 64-bit Alpha systems a three level mapping structure is used
// and up to 1gb of physical memory is identity mapped into KSEG0
// for PAL code access.
//
// One page is required for the first level page directory.
//
// One page is required for the kernel second level page directory.
//
// One page is required for each page table page in the identify map.
//
// One page is required for the page table page to map the shared page.
//
// One page is required for the shared page.
//
// Locate all pages in the first 1gb of physical memory and record
// page table page usage.
//
RtlZeroMemory(&PageMap[0], PAGE_MAP_SIZE);
ListHead = &LoaderBlock->MemoryDescriptorListHead;
NextEntry = ListHead->Flink;
do {
Descriptor = CONTAINING_RECORD(NextEntry,
MEMORY_ALLOCATION_DESCRIPTOR,
ListEntry);
Number = Descriptor->BasePage;
for (Count = 0; Count < Descriptor->PageCount; Count += 1) {
Index = Number >> (PDI2_SHIFT - PTI_SHIFT);
if (Index < PAGE_MAP_SIZE) {
PageMap[Index] = 1;
}
Number += 1;
}
NextEntry = NextEntry->Flink;
} while (NextEntry != ListHead);
//
// Compute the number of page table pages required to map the first
// 1gb of physical memory.
//
Total = 4;
for (Count = 0; Count < PAGE_MAP_SIZE; Count += 1) {
Total += PageMap[Count];
}
//
// Allocate a level 1 page directory page, a level 2 page directory
// page, a shared page table page, a shared data page, and the required
// number of pages to map up to 1gb of physical
// memory.
//
Status = BlAllocateAnyMemory(LoaderStartupPdrPage,
0,
Total,
&LoaderBlock->u.Alpha.PdrPage);
if (Status != ESUCCESS) {
return Status;
}
//
// Self map the level 1 directory into the level 1 directory, map the
// level 2 kernel page directory page into the level 1 page directory
// page, map the shared data page table page, and map all the
// page table pages into the level 2 page directory page so the first 1gb
// of physical memory can be accessed via KSEG0.
//
// Compute the address of the level one page directory page and zero
// the page.
//
PdrPage = LoaderBlock->u.Alpha.PdrPage;
Pdr1 = (PHARDWARE_PTE)(KSEG0_BASE | (PdrPage << PAGE_SHIFT));
RtlZeroMemory(Pdr1, PAGE_SIZE);
//
// Map the level one page directory identity entry in the level one
// page directory page.
//
Index = (PDE_BASE >> PDI1_SHIFT) & PDI_MASK;
Pdr1[Index].Valid = 1;
Pdr1[Index].KernelReadAccess = 1;
Pdr1[Index].KernelWriteAccess = 1;
Pdr1[Index].Write = 1;
Pdr1[Index].PageFrameNumber = PdrPage++;
//
// Map the level two kernel page directory page entry in the level one
// page directory page.
//
Index = (KSEG0_BASE >> PDI1_SHIFT) & PDI_MASK;
Pdr1[Index].Valid = 1;
Pdr1[Index].KernelReadAccess = 1;
Pdr1[Index].KernelWriteAccess = 1;
Pdr1[Index].Write = 1;
Pdr1[Index].PageFrameNumber = PdrPage;
//
// Compute the address of the level two kernel page directory page and
// zero the page.
//
Pdr2 = (PHARDWARE_PTE)(KSEG0_BASE | (PdrPage++ << PAGE_SHIFT));
RtlZeroMemory(Pdr2, PAGE_SIZE);
//
// Map the shared data page table page in the level two kernel page
// directory page.
//
Index = (KI_USER_SHARED_DATA >> PDI2_SHIFT) & PDI_MASK;
Pdr2[Index].Valid = 1;
Pdr2[Index].Global = 1;
Pdr2[Index].KernelReadAccess = 1;
Pdr2[Index].KernelWriteAccess = 1;
Pdr2[Index].Write = 1;
Pdr2[Index].PageFrameNumber = PdrPage;
//
// Compute the address of the shared data page table page and zero
// the page.
//
Ptp = (PHARDWARE_PTE)(KSEG0_BASE | (PdrPage++ << PAGE_SHIFT));
RtlZeroMemory(Ptp, PAGE_SIZE);
//
// Map the shared data page in the shared data page table page.
//
Index = (KI_USER_SHARED_DATA >> PTI_SHIFT) & PDI_MASK;
Ptp[Index].Valid = 1;
Ptp[Index].Global = 1;
Ptp[Index].KernelReadAccess = 1;
Ptp[Index].KernelWriteAccess = 1;
Ptp[Index].Write = 1;
Ptp[Index].PageFrameNumber = PdrPage;
//
// Compute the address of the shared data page and zero the page.
//
Ptp = (PHARDWARE_PTE)(KSEG0_BASE | (PdrPage++ << PAGE_SHIFT));
RtlZeroMemory(Ptp, PAGE_SIZE);
//
// Construct the identity map for the first 1gb of physical memory.
//
Base = (KSEG0_BASE >> PDI2_SHIFT) & PDI_MASK;
for (Count = 0; Count < PAGE_MAP_SIZE; Count += 1) {
if (PageMap[Count] != 0) {
Pdr2[Base | Count].Valid = 1;
Pdr2[Base | Count].Global = 1;
Pdr2[Base | Count].KernelReadAccess = 1;
Pdr2[Base | Count].KernelWriteAccess = 1;
Pdr2[Base | Count].Write = 1;
Pdr2[Base | Count].PageFrameNumber = PdrPage;
Ptp = (PHARDWARE_PTE)(KSEG0_BASE | (PdrPage << PAGE_SHIFT));
RtlZeroMemory(Ptp, PAGE_SIZE);
PdrPage += 1;
}
}
//
// Identity map the first 1gb of physical memory into KSEG0.
//
ListHead = &LoaderBlock->MemoryDescriptorListHead;
NextEntry = ListHead->Flink;
do {
Descriptor = CONTAINING_RECORD(NextEntry,
MEMORY_ALLOCATION_DESCRIPTOR,
ListEntry);
Number = Descriptor->BasePage;
for (Count = 0; Count < Descriptor->PageCount; Count += 1) {
Index = Number >> (PDI2_SHIFT - PTI_SHIFT);
if (Index < PAGE_MAP_SIZE) {
Ptp = (PHARDWARE_PTE)(KSEG0_BASE | (Pdr2[Base | Index].PageFrameNumber << PAGE_SHIFT));
Index = Number & PDI_MASK;
Ptp[Index].Valid = 1;
Ptp[Index].Global = 1;
Ptp[Index].KernelReadAccess = 1;
Ptp[Index].KernelWriteAccess = 1;
Ptp[Index].Write = 1;
Ptp[Index].PageFrameNumber = Number;
}
Number += 1;
}
NextEntry = NextEntry->Flink;
} while (NextEntry != ListHead);
//
// Set the granularity hint bits.
//
BlSetGranularityHints(Pdr1, Total);
return ESUCCESS;
}