|
|
/*++
Copyright (c) 1990, 1991 Microsoft Corporation
Module Name:
wake.c
Abstract:
Author:
Ken Reneris
Environment:
Kernel Mode
Revision History:
--*/
#include "arccodes.h"
#include "bootx86.h"
extern PHARDWARE_PTE PDE; extern PHARDWARE_PTE HalPT; extern ULONG HiberNoMappings; extern BOOLEAN HiberIoError; extern ULONG HiberLastRemap; extern BOOLEAN HiberOutOfRemap; PVOID HiberTransVa; ULONG HiberCurrentMapIndex;
#define PDE_SHIFT 22
#define PTE_SHIFT 12
#define PTE_INDEX_MASK 0x3ff
PVOID HbMapPte ( IN ULONG PteToMap, IN ULONG Page ) { PVOID Va;
Va = (PVOID) (HiberVa + (PteToMap << PAGE_SHIFT)); HbSetPte (Va, HiberPtes, PteToMap, Page); return Va; }
PVOID HbNextSharedPage ( IN ULONG PteToMap, IN ULONG RealPage ) /*++
Routine Description:
Allocates the next available page in the free and maps the Hiber pte to the page. The allocated page is put onto the remap list
Arguments:
PteToMap - Which Hiber PTE to map
RealPage - The page to enter into the remap table for this allocation
Return Value:
Virtual address of the mapping
--*/
{ PULONG MapPage; PULONG RemapPage; ULONG DestPage; ULONG i;
MapPage = (PULONG) (HiberVa + (PTE_MAP_PAGE << PAGE_SHIFT)); RemapPage = (PULONG) (HiberVa + (PTE_REMAP_PAGE << PAGE_SHIFT));
//
// Loop until we find a free page which is not in
// use by the loader image, then map it
//
while (HiberCurrentMapIndex < HiberNoMappings) { DestPage = MapPage[HiberCurrentMapIndex]; HiberCurrentMapIndex += 1;
i = HbPageDisposition (DestPage); if (i == HbPageInvalid) { HiberIoError = TRUE; return HiberBuffer; }
if (i == HbPageNotInUse) {
MapPage[HiberLastRemap] = DestPage; RemapPage[HiberLastRemap] = RealPage; HiberLastRemap += 1; HiberPageFrames[PteToMap] = DestPage; return HbMapPte(PteToMap, DestPage); } }
HiberOutOfRemap = TRUE; return HiberBuffer; }
VOID HbAllocatePtes ( IN ULONG NumberPages, OUT PVOID *PteAddress, OUT PVOID *MappedAddress ) /*++
Routine Description:
Allocated a consecutive chuck of Ptes.
Arguments:
NumberPage - Number of ptes to allocate
PteAddress - Pointer to the first PTE
MappedAddress - Base VA of the address mapped
--*/ { ULONG i; ULONG j;
//
// We use the HAL's PDE for mapping. Find enough free PTEs
//
for (i=0; i<=1024-NumberPages; i++) { for (j=0; j < NumberPages; j++) { if ((((PULONG)HalPT))[i+j]) { break; } }
if (j == NumberPages) { *PteAddress = (PVOID) &HalPT[i]; *MappedAddress = (PVOID) (0xffc00000 | (i<<12)); return ; } } BlPrint("NoMem"); while (1); }
VOID HbSetPte ( IN PVOID Va, IN PHARDWARE_PTE Pte, IN ULONG Index, IN ULONG PageNumber ) /*++
Routine Description:
Sets the Pte to the corresponding page address
--*/ { Pte[Index].PageFrameNumber = PageNumber; Pte[Index].Valid = 1; Pte[Index].Write = 1; Pte[Index].WriteThrough = 0; Pte[Index].CacheDisable = 0; _asm { mov eax, Va invlpg [eax] } }
VOID HiberSetupForWakeDispatch ( VOID ) { PHARDWARE_PTE HbPde; PHARDWARE_PTE HbPte; PHARDWARE_PTE WakePte; PHARDWARE_PTE TransVa; ULONG TransPde; ULONG WakePde; ULONG PteEntry;
//
// Allocate a transistion CR3. A page directory and table which
// contains the hibernation PTEs
//
HbPde = HbNextSharedPage(PTE_TRANSFER_PDE, 0); HbPte = HbNextSharedPage(PTE_WAKE_PTE, 0); // TRANSFER_PTE, 0);
RtlZeroMemory (HbPde, PAGE_SIZE); RtlZeroMemory (HbPte, PAGE_SIZE);
//
// Set PDE to point to PTE
//
TransPde = ((ULONG) HiberVa) >> PDE_SHIFT; HbPde[TransPde].PageFrameNumber = HiberPageFrames[PTE_WAKE_PTE]; HbPde[TransPde].Write = 1; HbPde[TransPde].Valid = 1;
//
// Fill in the hiber PTEs
//
PteEntry = (((ULONG) HiberVa) >> PTE_SHIFT) & PTE_INDEX_MASK; TransVa = &HbPte[PteEntry]; RtlCopyMemory (TransVa, HiberPtes, HIBER_PTES * sizeof(HARDWARE_PTE));
//
// Make another copy at the Va of the wake image hiber ptes
//
WakePte = HbPte; WakePde = ((ULONG) HiberIdentityVa) >> PDE_SHIFT; if (WakePde != TransPde) { WakePte = HbNextSharedPage(PTE_WAKE_PTE, 0); HbPde[WakePde].PageFrameNumber = HiberPageFrames[PTE_WAKE_PTE]; HbPde[WakePde].Write = 1; HbPde[WakePde].Valid = 1; }
PteEntry = (((ULONG) HiberIdentityVa) >> PTE_SHIFT) & PTE_INDEX_MASK; TransVa = &WakePte[PteEntry]; RtlCopyMemory (TransVa, HiberPtes, HIBER_PTES * sizeof(HARDWARE_PTE));
//
// Set TransVa to be relative to the va of the transfer Cr3
//
HiberTransVa = (PVOID) (((PUCHAR) TransVa) - HiberVa + (PUCHAR) HiberIdentityVa); }
|