284 lines
7.5 KiB
C
284 lines
7.5 KiB
C
/*++
|
||
|
||
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;
|
||
}
|