mirror of https://github.com/tongzx/nt5src
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
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;
|
|
}
|