Esempio n. 1
0
PVOID
NTAPI
MiMapPageInHyperSpace(IN PEPROCESS Process,
                      IN PFN_NUMBER Page,
                      IN PKIRQL OldIrql)
{
    MMPTE TempPte;
    PMMPTE PointerPte;
    PFN_NUMBER Offset;

    //
    // Never accept page 0 or non-physical pages
    //
    ASSERT(Page != 0);
    ASSERT(MiGetPfnEntry(Page) != NULL);

    //
    // Build the PTE
    //
    TempPte = ValidKernelPteLocal;
    TempPte.u.Hard.PageFrameNumber = Page;

    //
    // Pick the first hyperspace PTE
    //
    PointerPte = MmFirstReservedMappingPte;

    //
    // Acquire the hyperlock
    //
    ASSERT(Process == PsGetCurrentProcess());
    KeAcquireSpinLock(&Process->HyperSpaceLock, OldIrql);

    //
    // Now get the first free PTE
    //
    Offset = PFN_FROM_PTE(PointerPte);
    if (!Offset)
    {
        //
        // Reset the PTEs
        //
        Offset = MI_HYPERSPACE_PTES;
        KeFlushProcessTb();
    }

    //
    // Prepare the next PTE
    //
    PointerPte->u.Hard.PageFrameNumber = Offset - 1;

    //
    // Write the current PTE
    //
    PointerPte += Offset;
    MI_WRITE_VALID_PTE(PointerPte, TempPte);

    //
    // Return the address
    //
    return MiPteToAddress(PointerPte);
}
Esempio n. 2
0
PMMPTE
NTAPI
MiReserveAlignedSystemPtes(IN ULONG NumberOfPtes,
                           IN MMSYSTEM_PTE_POOL_TYPE SystemPtePoolType,
                           IN ULONG Alignment)
{
    KIRQL OldIrql;
    PMMPTE PreviousPte, NextPte, ReturnPte;
    ULONG ClusterSize;

    //
    // Sanity check
    //
    ASSERT(Alignment <= PAGE_SIZE);

    //
    // Acquire the System PTE lock
    //
    OldIrql = KeAcquireQueuedSpinLock(LockQueueSystemSpaceLock);

    //
    // Find the last cluster in the list that doesn't contain enough PTEs
    //
    PreviousPte = &MmFirstFreeSystemPte[SystemPtePoolType];

    while (PreviousPte->u.List.NextEntry != MM_EMPTY_PTE_LIST)
    {
        //
        // Get the next cluster and its size
        //
        NextPte = MmSystemPteBase + PreviousPte->u.List.NextEntry;
        ClusterSize = MI_GET_CLUSTER_SIZE(NextPte);

        //
        // Check if this cluster contains enough PTEs
        //
        if (NumberOfPtes <= ClusterSize)
            break;

        //
        // On to the next cluster
        //
        PreviousPte = NextPte;
    }

    //
    // Make sure we didn't reach the end of the cluster list
    //
    if (PreviousPte->u.List.NextEntry == MM_EMPTY_PTE_LIST)
    {
        //
        // Release the System PTE lock and return failure
        //
        KeReleaseQueuedSpinLock(LockQueueSystemSpaceLock, OldIrql);
        return NULL;
    }

    //
    // Unlink the cluster
    //
    PreviousPte->u.List.NextEntry = NextPte->u.List.NextEntry;

    //
    // Check if the reservation spans the whole cluster
    //
    if (ClusterSize == NumberOfPtes)
    {
        //
        // Return the first PTE of this cluster
        //
        ReturnPte = NextPte;

        //
        // Zero the cluster
        //
        if (NextPte->u.List.OneEntry == 0)
        {
            NextPte->u.Long = 0;
            NextPte++;
        }
        NextPte->u.Long = 0;
    }
    else
    {
        //
        // Divide the cluster into two parts
        //
        ClusterSize -= NumberOfPtes;
        ReturnPte = NextPte + ClusterSize;

        //
        // Set the size of the first cluster, zero the second if needed
        //
        if (ClusterSize == 1)
        {
            NextPte->u.List.OneEntry = 1;
            ReturnPte->u.Long = 0;
        }
        else
        {
            NextPte++;
            NextPte->u.List.NextEntry = ClusterSize;
        }

        //
        // Step through the cluster list to find out where to insert the first
        //
        PreviousPte = &MmFirstFreeSystemPte[SystemPtePoolType];

        while (PreviousPte->u.List.NextEntry != MM_EMPTY_PTE_LIST)
        {
            //
            // Get the next cluster
            //
            NextPte = MmSystemPteBase + PreviousPte->u.List.NextEntry;

            //
            // Check if the cluster to insert is smaller or of equal size
            //
            if (ClusterSize <= MI_GET_CLUSTER_SIZE(NextPte))
                break;

            //
            // On to the next cluster
            //
            PreviousPte = NextPte;
        }

        //
        // Retrieve the first cluster and link it back into the cluster list
        //
        NextPte = ReturnPte - ClusterSize;

        NextPte->u.List.NextEntry = PreviousPte->u.List.NextEntry;
        PreviousPte->u.List.NextEntry = NextPte - MmSystemPteBase;
    }

    //
    // Decrease availability
    //
    MmTotalFreeSystemPtes[SystemPtePoolType] -= NumberOfPtes;

    //
    // Release the System PTE lock
    //
    KeReleaseQueuedSpinLock(LockQueueSystemSpaceLock, OldIrql);

    //
    // Flush the TLB
    //
    KeFlushProcessTb();

    //
    // Return the reserved PTEs
    //
    return ReturnPte;
}
Esempio n. 3
0
PVOID
NTAPI
MiMapPagesInZeroSpace(IN PMMPFN Pfn1,
                      IN PFN_NUMBER NumberOfPages)
{
    MMPTE TempPte;
    PMMPTE PointerPte;
    PFN_NUMBER Offset, PageFrameIndex;

    //
    // Sanity checks
    //
    ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);
    ASSERT(NumberOfPages != 0);
    ASSERT(NumberOfPages <= (MI_ZERO_PTES - 1));

    //
    // Pick the first zeroing PTE
    //
    PointerPte = MiFirstReservedZeroingPte;

    //
    // Now get the first free PTE
    //
    Offset = PFN_FROM_PTE(PointerPte);
    if (NumberOfPages > Offset)
    {
        //
        // Reset the PTEs
        //
        Offset = MI_ZERO_PTES - 1;
        PointerPte->u.Hard.PageFrameNumber = Offset;
        KeFlushProcessTb();
    }

    //
    // Prepare the next PTE
    //
    PointerPte->u.Hard.PageFrameNumber = Offset - NumberOfPages;

    /* Choose the correct PTE to use, and which template */
    PointerPte += (Offset + 1);
    TempPte = ValidKernelPte;

    /* Make sure the list isn't empty and loop it */
    ASSERT(Pfn1 != (PVOID)LIST_HEAD);
    while (Pfn1 != (PVOID)LIST_HEAD)
    {
        /* Get the page index for this PFN */
        PageFrameIndex = MiGetPfnEntryIndex(Pfn1);

        //
        // Write the PFN
        //
        TempPte.u.Hard.PageFrameNumber = PageFrameIndex;

        //
        // Set the correct PTE to write to, and set its new value
        //
        PointerPte--;
        MI_WRITE_VALID_PTE(PointerPte, TempPte);

        /* Move to the next PFN */
        Pfn1 = (PMMPFN)Pfn1->u1.Flink;
    }

    //
    // Return the address
    //
    return MiPteToAddress(PointerPte);
}