示例#1
0
/*

Blocking function to acquire zeroed pages from the balancer.

Upon entry:

Required->Amount: Number of pages to acquire
Required->Consumer: consumer to charge the page to

Upon return:

Required->Pages[0..Amount]: Allocated pages.

The function fails unless all requested pages can be allocated.

 */
NTSTATUS
NTAPI
MiGetOnePage(PMMSUPPORT AddressSpace,
             PMEMORY_AREA MemoryArea,
             PMM_REQUIRED_RESOURCES Required)
{
    ULONG i;
    NTSTATUS Status = STATUS_SUCCESS;

    for (i = 0; i < Required->Amount; i++)
    {
        DPRINTC("MiGetOnePage(%s:%d)\n", Required->File, Required->Line);
        Status = MmRequestPageMemoryConsumer(Required->Consumer,
                                             TRUE,
                                             &Required->Page[i]);
        if (!NT_SUCCESS(Status))
        {
            while (i > 0)
            {
                MmReleasePageMemoryConsumer(Required->Consumer,
                                            Required->Page[i-1]);
                i--;
            }
            return Status;
        }
    }

    return Status;
}
示例#2
0
文件: sptab.c 项目: hoangduit/reactos
ULONG_PTR
NTAPI
_MmGetPageEntrySectionSegment(PMM_SECTION_SEGMENT Segment,
                              PLARGE_INTEGER Offset,
                              const char *file,
                              int line)
{
    LARGE_INTEGER FileOffset;
    ULONG_PTR PageIndex, Result;
    PCACHE_SECTION_PAGE_TABLE PageTable;

    ASSERT(Segment->Locked);
    FileOffset.QuadPart = ROUND_DOWN(Offset->QuadPart,
                                     ENTRIES_PER_ELEMENT * PAGE_SIZE);
    PageTable = MiSectionPageTableGet(&Segment->PageTable, &FileOffset);
    if (!PageTable) return 0;
    PageIndex = (ULONG_PTR)((Offset->QuadPart - PageTable->FileOffset.QuadPart) / PAGE_SIZE);
    Result = PageTable->PageEntries[PageIndex];
#if 0
    DPRINTC
        ("MiGetPageEntrySectionSegment(%p,%08x%08x) => %x %s:%d\n",
         Segment,
         FileOffset.u.HighPart,
         FileOffset.u.LowPart + PageIndex * PAGE_SIZE,
         Result,
         file, line);
#endif
    return Result;
}
示例#3
0
NTSTATUS
NTAPI
MmNotPresentFaultCacheSection(KPROCESSOR_MODE Mode,
                              ULONG_PTR Address,
                              BOOLEAN FromMdl)
{
    PETHREAD Thread;
    PMMSUPPORT AddressSpace;
    NTSTATUS Status;

    Address &= ~(PAGE_SIZE - 1);
    DPRINT("MmNotPresentFault(Mode %d, Address %Ix)\n", Mode, Address);

    Thread = PsGetCurrentThread();

    if (KeGetCurrentIrql() >= DISPATCH_LEVEL)
    {
        DPRINT1("Page fault at high IRQL %u, address %Ix\n",
                KeGetCurrentIrql(),
                Address);

        ASSERT(FALSE);
        return STATUS_UNSUCCESSFUL;
    }

    /* Find the memory area for the faulting address */
    if (Address >= (ULONG_PTR)MmSystemRangeStart)
    {
        /* Check permissions */
        if (Mode != KernelMode)
        {
            DPRINTC("Address: %x\n", Address);
            return STATUS_ACCESS_VIOLATION;
        }
        AddressSpace = MmGetKernelAddressSpace();
    }
    else
    {
        AddressSpace = &PsGetCurrentProcess()->Vm;
    }

    Thread->ActiveFaultCount++;
    Status = MmNotPresentFaultCacheSectionInner(Mode,
                                                AddressSpace,
                                                Address,
                                                FromMdl,
                                                Thread);
    Thread->ActiveFaultCount--;

    ASSERT(Status != STATUS_UNSUCCESSFUL);
    ASSERT(Status != STATUS_INVALID_PARAMETER);
    DPRINT("MmAccessFault %p:%Ix -> %x\n",
           MmGetAddressSpaceOwner(AddressSpace),
           Address,
           Status);

    return Status;
}
static void ftt_detect_pad_statistics(struct ftt_charger_device *ftt_pdev)
{
	u32 count;

	ftt_pdev->ftt_detect_pad_statistics_count[ftt_pdev->detect_pad]++;
	ftt_pdev->ftt_detect_pad_statistics_total++;
	DPRINT(FTT_LOG_PAD_DETECT_TEST, "####################### STATISTICS #######################\n");
	DPRINT(FTT_LOG_PAD_DETECT_TEST, "STATISTICS : ");
	for (count = 1;count < FTT_PAD_TYPE_MAX;count++) {
		if (ftt_pdev->ftt_detect_pad_statistics_count[count] != 0) {
			DPRINTC(FTT_LOG_PAD_DETECT_TEST, "%d=%u(%u%%), ", count,
					ftt_pdev->ftt_detect_pad_statistics_count[count],
					ftt_pdev->ftt_detect_pad_statistics_count[count]*100/ftt_pdev->ftt_detect_pad_statistics_total);
		}
	}
	DPRINTC(FTT_LOG_PAD_DETECT_TEST, "total=%u\n", ftt_pdev->ftt_detect_pad_statistics_total);
	DPRINT(FTT_LOG_PAD_DETECT_TEST, "##########################################################\n");
}
示例#5
0
SServerConfigs * serverConfigInit(SircConfig *generic_configs)
{
    SServerConfigs *_this;
	DPRINTC(PrintComp_IrcCfg,"Initializing server configs. Upperlayer struct at %p",generic_configs);
	MAZZERT(NULL!=generic_configs,"NULL arg given to serverConfigInit()");
    _this=malloc(sizeof(SServerConfigs));
    if(NULL==_this)
    {
        PPRINTC(PrintComp_IrcCfg,"Alloc failed at serverConfigInit()");
        return NULL;
    }
    memset(_this,0,sizeof(SServerConfigs));
	_this->generic_configs=generic_configs;
	_this->type=EcfgStructType_server;
    _this->ServerConfigsCfgAdd=&ServerConfigsCfgAdd;
	_this->serverEventConfAdd=&serverEventConfAdd;
	DPRINTC(PrintComp_IrcCfg,"serverConfigInit - server config struct initialized at %p",_this);
    return _this;
}
示例#6
0
static int ServerConfigsCfgAdd(SServerConfigs *_this,SmbotPseudoxmlTag* serverRootTag)
{
    size_t servernamelen;
	int allocd_channels;
	int allocd_events;
    SmbotPseudoxmlTag *temptag;
    //SmbotPseudoxmlTag *chantag;

    /* Sanity checks */
    MAZZERT(NULL!=_this && NULL!=serverRootTag,"NULL ptr given to ServerConfigsCfgAdd()");
    MAZZERT( !strcmp(serverRootTag->name, "server"),"tag which type is not 'server' given to ServerConfigsCfgAdd() as root tag!");
    MAZZERT( serverRootTag->valuetype==EmbotPseudoxmlType_char,"Unsupported type for server tag!");
    MAZZERT( (int)serverRootTag->size > 0,"Zero or negative server name lenght!");
    servernamelen=strlen(serverRootTag->value);
    if(servernamelen>=sizeof(_this->domain))
    {
        EPRINTC(PrintComp_IrcCfg,"Too long server domain given! Max lenght %u chars",sizeof(_this->domain));
        return -1;
    }
    /* Fill server name */
    memcpy(_this->domain,serverRootTag->value,servernamelen+1);
    if(NULL==serverRootTag->subtags)
    {
        WPRINTC(PrintComp_IrcCfg,"No channels. users or other configs given for server %s",_this->domain);
    }
    /* Loop through the subtags && set values */
    DPRINTC(PrintComp_IrcCfg,"Tags preparsed => starting to fill channel structs");
    allocd_channels=10;
	allocd_events=10;
    _this->channels=malloc(allocd_channels*sizeof(SChannelConfigs *));
 	_this->events=malloc(allocd_events*sizeof(SServerEvents *));
	if(NULL==_this->channels || NULL == _this->events)
	{
		PPRINTC(PrintComp_IrcCfg,"malloc failed, out of mem??");
		return -1;
	}
    temptag=serverRootTag->subtags;
    for(;NULL!=temptag;)
    {
        if(!strcmp(temptag->name,"channel"))
        {
			DPRINTC(PrintComp_IrcCfg,"Found channel for server %s",_this->domain);
            /* Depth 1 channel tag parsing */
            if(allocd_channels<=_this->amntofchannels)
            {
				DPRINTC(PrintComp_IrcCfg,
						"Channel %d, but allocated only %d slots => reallocking to %d slots",
						_this->amntofchannels+1,
						allocd_channels,
						allocd_channels+10
				);
                allocd_channels+=10;
                _this->channels=realloc(_this->channels,sizeof(SChannelConfigs *)*allocd_channels);
                if(NULL==_this->channels)
                {
                    PPRINTC(PrintComp_IrcCfg,"Realloc failed while allocating space for channel specific configs!");
                    return -1;
                }
            }
			DPRINTC(PrintComp_IrcCfg,"Initializing channel[%d] for server %s",_this->amntofchannels,_this->domain);
            _this->channels[_this->amntofchannels]=channelConfigInit(_this);
            if(NULL==_this->channels[_this->amntofchannels])
            {
                PPRINTC(PrintComp_IrcCfg,"ChannelCfgInit FAILED");
                return -1;
            }
            if(0!=_this->channels[_this->amntofchannels]->ChannelConfigsCfgAdd(_this->channels[_this->amntofchannels],temptag))
            {
                EPRINTC(PrintComp_IrcCfg,"Final parsing for channel %s configs FAILED!",(char *)temptag->value);
                return -1;
            }
			DPRINTC(PrintComp_IrcCfg,
					"Channel %s at index[%d] adding successfull for server %s",
					_this->channels[_this->amntofchannels]->chan,
					_this->amntofchannels,
					_this->domain
			);
            DPRINTC(PrintComp_IrcCfg,"Channel configs successfully parsed for channel %s",(char *)temptag->value);
			_this->amntofchannels++;
        }
        else if(!strcmp(temptag->name,"port"))
        {
            DPRINTC(PrintComp_IrcCfg,"Port tag for server %s found, processing...",_this->domain);
            if(temptag->valuetype!=EmbotPseudoxmlType_16bit)
            {
                WPRINTC(PrintComp_IrcCfg,"Port tag for server %s is not expected type '16bit'",_this->domain);
                
            }
            /* TODO: Add function / macro to do this conversion safely */
            if(EmbotPseudoxmlType_8bit==temptag->valuetype || EmbotPseudoxmlType_char==temptag->valuetype)
                _this->port=*(unsigned char *)temptag->value;
            else if(EmbotPseudoxmlType_16bit==temptag->valuetype)
                _this->port=*(unsigned short *)temptag->value;
            else if(EmbotPseudoxmlType_32bit == temptag->valuetype)
                _this->port=(unsigned short int)*(unsigned int *)temptag->value;
            else if(EmbotPseudoxmlType_64bit == temptag->valuetype)
                _this->port=(unsigned short int)*(unsigned long long int *)temptag->value;
        }
		else if(!strcmp(temptag->name,"user"))
		{
			DPRINTC(PrintComp_IrcCfg,"Found user for server %s, adding..",_this->domain);
			if(_this->generic_configs->ircUserConfAdd(_this,temptag))	
			{
				EPRINTC(PrintComp_IrcCfg,"User adding for server %s FAILED",_this->domain);
				return -1;
			}
			DPRINTC(PrintComp_IrcCfg,
					"User at index %d (nick=%s) added to server %s",
					_this->useramnt-1,
					_this->users[_this->useramnt-1]->nick,
					_this->domain
			);
//			_this->useramnt++;
		}
		else if(!strcmp(temptag->name,"event"))
		{
			if(allocd_events<=_this->amntofevents)
            {
				DPRINTC(PrintComp_IrcCfg,
						"Event %d, but allocated only %d slots => reallocking to %d slots",
						_this->amntofevents+1,
						allocd_events,
						allocd_events+10
				);
                allocd_events+=10;
                _this->events=realloc(_this->events,sizeof(SServerEvents *)*allocd_events);
                if(NULL==_this->events)
                {
                    PPRINTC(PrintComp_IrcCfg,"Realloc failed while allocating space for event specific configs!");
                    return -1;
                }
            }

			if(_this->serverEventConfAdd(_this,temptag))
			{
				EPRINTC(PrintComp_IrcCfg,"Event adding for server %s FAILED",_this->domain);
				return -1;
			}
		}
		else if(!strcmp(temptag->name,"botnick"))
		{
			if(temptag->subtags!=NULL)
			{
				EPRINTC(PrintComp_IrcCfg,"tag botnick should be closed!");
				return -1;
			}
			if(temptag->valuetype!=EmbotPseudoxmlType_char)
			{
				EPRINTC(PrintComp_IrcCfg,"tag botnick has bad valuetype, should be EmbotPseudoxmlType_char!");
				return -1;
			}
    		if( (int)temptag->size <= 0 || temptag->size>sizeof(Tircnick))
			{
				EPRINTC(PrintComp_IrcCfg,"Zero or negative bot name lenght!");
				return -1;
			}
			memcpy(_this->mynick,temptag->value,sizeof(Tircnick));
		}
        /* else if(!strcmp(temptag->name,"ADD HERE OTHER ALLOWED TAGS AT SERVER LEVEL") */
        else
        {
            EPRINTC(PrintComp_IrcCfg,"Unknown server config %s given! - ignoring",temptag->name);
        }
        temptag=temptag->next;

    }
    /* Check that compulsory tags are given */
    if(0==_this->port)
    {
        WPRINTC(PrintComp_IrcCfg,"No port given for server %s => assuming 6667",_this->domain);
       _this->port=6667;
    }
	
	if('\0'==_this->generic_configs->mynick[0] && '\0'==_this->mynick[0])
	{
		WPRINTC(PrintComp_IrcCfg,"No generic or server specific nickname given when server %s seems to be configured!",_this->domain);
		DPRINTC(PrintComp_IrcCfg,"This is not fatal, since nothing says the 'botnick' cannot be given after server specific stuff");
	}
   return 0; 
}
示例#7
0
NTSTATUS
NTAPI
MmNotPresentFaultCacheSectionInner(KPROCESSOR_MODE Mode,
                                   PMMSUPPORT AddressSpace,
                                   ULONG_PTR Address,
                                   BOOLEAN FromMdl,
                                   PETHREAD Thread)
{
    BOOLEAN Locked = FromMdl;
    PMEMORY_AREA MemoryArea;
    MM_REQUIRED_RESOURCES Resources = { 0 };
    WORK_QUEUE_WITH_CONTEXT Context;
    NTSTATUS Status = STATUS_SUCCESS;

    RtlZeroMemory(&Context, sizeof(WORK_QUEUE_WITH_CONTEXT));

    if (!FromMdl)
    {
        MmLockAddressSpace(AddressSpace);
    }

    /* Call the memory area specific fault handler */
    do
    {
        MemoryArea = MmLocateMemoryAreaByAddress(AddressSpace, (PVOID)Address);
        if (MemoryArea == NULL || MemoryArea->DeleteInProgress)
        {
            Status = STATUS_ACCESS_VIOLATION;
            if (MemoryArea)
            {
                DPRINT1("Type %x DIP %x\n",
                        MemoryArea->Type,
                        MemoryArea->DeleteInProgress);
            }
            else
            {
                DPRINT1("No memory area\n");
            }
            DPRINT1("Process %p, Address %Ix\n",
                    MmGetAddressSpaceOwner(AddressSpace),
                    Address);
            break;
        }

        DPRINTC("Type %x (%p -> %08Ix -> %p) in %p\n",
                MemoryArea->Type,
                MemoryArea->StartingAddress,
                Address,
                MemoryArea->EndingAddress,
                PsGetCurrentThread());

        Resources.DoAcquisition = NULL;

        // Note: fault handlers are called with address space locked
        // We return STATUS_MORE_PROCESSING_REQUIRED if anything is needed

        Status = MmNotPresentFaultCachePage(AddressSpace,
                                            MemoryArea,
                                            (PVOID)Address,
                                            Locked,
                                            &Resources);

        if (!FromMdl)
        {
            MmUnlockAddressSpace(AddressSpace);
        }

        if (Status == STATUS_SUCCESS)
        {
            ; // Nothing
        }
        else if (Status == STATUS_SUCCESS + 1)
        {
            /* Wait page ... */
            DPRINT("Waiting for %Ix\n", Address);
            MiWaitForPageEvent(MmGetAddressSpaceOwner(AddressSpace), Address);
            DPRINT("Done waiting for %Ix\n", Address);
            Status = STATUS_MM_RESTART_OPERATION;
        }
        else if (Status == STATUS_MM_RESTART_OPERATION)
        {
            /* Clean slate */
            DPRINT("Clear resource\n");
            RtlZeroMemory(&Resources, sizeof(Resources));
        }
        else if (Status == STATUS_MORE_PROCESSING_REQUIRED)
        {
            if (Thread->ActiveFaultCount > 2)
            {
                DPRINTC("Already fault handling ... going to work item (%Ix)\n", Address);
                Context.AddressSpace = AddressSpace;
                Context.MemoryArea = MemoryArea;
                Context.Required = &Resources;
                KeInitializeEvent(&Context.Wait, NotificationEvent, FALSE);

                ExInitializeWorkItem(&Context.WorkItem,
                                     (PWORKER_THREAD_ROUTINE)MmpFaultWorker,
                                     &Context);

                DPRINT("Queue work item\n");
                ExQueueWorkItem(&Context.WorkItem, DelayedWorkQueue);
                DPRINT("Wait\n");
                KeWaitForSingleObject(&Context.Wait, 0, KernelMode, FALSE, NULL);
                Status = Context.Status;
                DPRINTC("Status %x\n", Status);
            }
            else
            {
                DPRINT("DoAcquisition %p\n", Resources.DoAcquisition);

                Status = Resources.DoAcquisition(AddressSpace,
                                                 MemoryArea,
                                                 &Resources);

                DPRINT("DoAcquisition %p -> %x\n",
                       Resources.DoAcquisition,
                       Status);
            }

            if (NT_SUCCESS(Status))
            {
                Status = STATUS_MM_RESTART_OPERATION;
            }
        }
        else if (NT_SUCCESS(Status))
        {
            ASSERT(FALSE);
        }

        if (!FromMdl)
        {
            MmLockAddressSpace(AddressSpace);
        }
    }
    while (Status == STATUS_MM_RESTART_OPERATION);

    DPRINTC("Completed page fault handling: %p:%Ix %x\n",
            MmGetAddressSpaceOwner(AddressSpace),
            Address,
            Status);

    if (!FromMdl)
    {
        MmUnlockAddressSpace(AddressSpace);
    }

    MiSetPageEvent(MmGetAddressSpaceOwner(AddressSpace), Address);
    DPRINT("Done %x\n", Status);

    return Status;
}
示例#8
0
NTSTATUS
NTAPI
MiCowCacheSectionPage (
    _In_ PMMSUPPORT AddressSpace,
    _In_ PMEMORY_AREA MemoryArea,
    _In_ PVOID Address,
    _In_ BOOLEAN Locked,
    _Inout_ PMM_REQUIRED_RESOURCES Required)
{
    PMM_SECTION_SEGMENT Segment;
    PFN_NUMBER NewPage, OldPage;
    NTSTATUS Status;
    PVOID PAddress;
    LARGE_INTEGER Offset;
    PEPROCESS Process = MmGetAddressSpaceOwner(AddressSpace);

    DPRINT("MmAccessFaultSectionView(%p, %p, %p, %u)\n",
           AddressSpace,
           MemoryArea,
           Address,
           Locked);

    Segment = MemoryArea->Data.SectionData.Segment;

   /* Lock the segment */
    MmLockSectionSegment(Segment);

   /* Find the offset of the page */
    PAddress = MM_ROUND_DOWN(Address, PAGE_SIZE);
    Offset.QuadPart = (ULONG_PTR)PAddress - (ULONG_PTR)MemoryArea->StartingAddress +
                      MemoryArea->Data.SectionData.ViewOffset.QuadPart;

    if (!Segment->WriteCopy /*&&
        !MemoryArea->Data.SectionData.WriteCopyView*/ ||
        Segment->Image.Characteristics & IMAGE_SCN_MEM_SHARED)
    {
#if 0
        if (Region->Protect == PAGE_READWRITE ||
            Region->Protect == PAGE_EXECUTE_READWRITE)
#endif
        {
            ULONG_PTR Entry;
            DPRINTC("setting non-cow page %p %p:%p offset %I64x (%Ix) to writable\n",
                    Segment,
                    Process,
                    PAddress,
                    Offset.QuadPart,
                    MmGetPfnForProcess(Process, Address));
            if (Segment->FileObject)
            {
                DPRINTC("file %wZ\n", &Segment->FileObject->FileName);
            }
            Entry = MmGetPageEntrySectionSegment(Segment, &Offset);
            DPRINT("Entry %x\n", Entry);
            if (Entry &&
                !IS_SWAP_FROM_SSE(Entry) &&
                PFN_FROM_SSE(Entry) == MmGetPfnForProcess(Process, Address)) {

                MmSetPageEntrySectionSegment(Segment,
                                             &Offset,
                                             DIRTY_SSE(Entry));
            }
            MmSetPageProtect(Process, PAddress, PAGE_READWRITE);
            MmSetDirtyPage(Process, PAddress);
            MmUnlockSectionSegment(Segment);
            DPRINT("Done\n");
            return STATUS_SUCCESS;
        }
#if 0
        else
        {
            DPRINT("Not supposed to be writable\n");
            MmUnlockSectionSegment(Segment);
            return STATUS_ACCESS_VIOLATION;
        }
#endif
    }

    if (!Required->Page[0])
    {
        SWAPENTRY SwapEntry;
        if (MmIsPageSwapEntry(Process, Address))
        {
            MmGetPageFileMapping(Process, Address, &SwapEntry);
            MmUnlockSectionSegment(Segment);
            if (SwapEntry == MM_WAIT_ENTRY)
                return STATUS_SUCCESS + 1; // Wait ... somebody else is getting it right now
            else
                return STATUS_SUCCESS; // Nonwait swap entry ... handle elsewhere
        }
        /* Call out to acquire a page to copy to.  We'll be re-called when
         * the page has been allocated. */
        Required->Page[1] = MmGetPfnForProcess(Process, Address);
        Required->Consumer = MC_CACHE;
        Required->Amount = 1;
        Required->File = __FILE__;
        Required->Line = __LINE__;
        Required->DoAcquisition = MiGetOnePage;
        MmCreatePageFileMapping(Process, Address, MM_WAIT_ENTRY);
        MmUnlockSectionSegment(Segment);
        return STATUS_MORE_PROCESSING_REQUIRED;
    }

    NewPage = Required->Page[0];
    OldPage = Required->Page[1];

    DPRINT("Allocated page %x\n", NewPage);

    /* Unshare the old page */
    MmDeleteRmap(OldPage, Process, PAddress);

   /* Copy the old page */
    DPRINT("Copying\n");
    MiCopyPageToPage(NewPage, OldPage);

   /* Set the PTE to point to the new page */
    Status = MmCreateVirtualMapping(Process,
                                    Address,
                                    PAGE_READWRITE,
                                    &NewPage,
                                    1);

    if (!NT_SUCCESS(Status))
    {
        DPRINT1("MmCreateVirtualMapping failed, not out of memory\n");
        ASSERT(FALSE);
        MmUnlockSectionSegment(Segment);
        return Status;
    }

    MmInsertRmap(NewPage, Process, PAddress);
    MmReleasePageMemoryConsumer(MC_CACHE, OldPage);
    MmUnlockSectionSegment(Segment);

    DPRINT("Address 0x%p\n", Address);
    return STATUS_SUCCESS;
}
示例#9
0
NTSTATUS
NTAPI
MmNotPresentFaultCachePage (
    _In_ PMMSUPPORT AddressSpace,
    _In_ MEMORY_AREA* MemoryArea,
    _In_ PVOID Address,
    _In_ BOOLEAN Locked,
    _Inout_ PMM_REQUIRED_RESOURCES Required)
{
    NTSTATUS Status;
    PVOID PAddress;
    ULONG Consumer;
    PMM_SECTION_SEGMENT Segment;
    LARGE_INTEGER FileOffset, TotalOffset;
    ULONG_PTR Entry;
    ULONG Attributes;
    PEPROCESS Process = MmGetAddressSpaceOwner(AddressSpace);
    KIRQL OldIrql;

    DPRINT("Not Present: %p %p (%p-%p)\n",
           AddressSpace,
           Address,
           MemoryArea->StartingAddress,
           MemoryArea->EndingAddress);

    /*
     * There is a window between taking the page fault and locking the
     * address space when another thread could load the page so we check
     * that.
     */
    if (MmIsPagePresent(Process, Address))
    {
        DPRINT("Done\n");
        return STATUS_SUCCESS;
    }

    PAddress = MM_ROUND_DOWN(Address, PAGE_SIZE);
    TotalOffset.QuadPart = (ULONG_PTR)PAddress -
                           (ULONG_PTR)MemoryArea->StartingAddress;

    Segment = MemoryArea->Data.SectionData.Segment;

    TotalOffset.QuadPart += MemoryArea->Data.SectionData.ViewOffset.QuadPart;
    FileOffset = TotalOffset;

    //Consumer = (Segment->Flags & MM_DATAFILE_SEGMENT) ? MC_CACHE : MC_USER;
    Consumer = MC_CACHE;

    if (Segment->FileObject)
    {
        DPRINT("FileName %wZ\n", &Segment->FileObject->FileName);
    }

    DPRINT("Total Offset %08x%08x\n", TotalOffset.HighPart, TotalOffset.LowPart);

    /* Lock the segment */
    MmLockSectionSegment(Segment);

    /* Get the entry corresponding to the offset within the section */
    Entry = MmGetPageEntrySectionSegment(Segment, &TotalOffset);

    Attributes = PAGE_READONLY;

    if (Required->State && Required->Page[0])
    {
        DPRINT("Have file and page, set page %x in section @ %x #\n",
               Required->Page[0],
               TotalOffset.LowPart);

        if (Required->SwapEntry)
            MmSetSavedSwapEntryPage(Required->Page[0], Required->SwapEntry);

        if (Required->State & 2)
        {
            DPRINT("Set in section @ %x\n", TotalOffset.LowPart);
            Status = MmSetPageEntrySectionSegment(Segment,
                                                  &TotalOffset,
                                                  Entry = MAKE_PFN_SSE(Required->Page[0]));
            if (!NT_SUCCESS(Status))
            {
                MmReleasePageMemoryConsumer(MC_CACHE, Required->Page[0]);
            }
            MmUnlockSectionSegment(Segment);
            MiSetPageEvent(Process, Address);
            DPRINT("Status %x\n", Status);
            return STATUS_MM_RESTART_OPERATION;
        }
        else
        {
            DPRINT("Set %x in address space @ %p\n", Required->Page[0], Address);
            Status = MmCreateVirtualMapping(Process,
                                            Address,
                                            Attributes,
                                            Required->Page,
                                            1);
            if (NT_SUCCESS(Status))
            {
                MmInsertRmap(Required->Page[0], Process, Address);
            }
            else
            {
                /* Drop the reference for our address space ... */
                MmReleasePageMemoryConsumer(MC_CACHE, Required->Page[0]);
            }
            MmUnlockSectionSegment(Segment);
            DPRINTC("XXX Set Event %x\n", Status);
            MiSetPageEvent(Process, Address);
            DPRINT("Status %x\n", Status);
            return Status;
        }
    }
    else if (MM_IS_WAIT_PTE(Entry))
    {
        // Whenever MM_WAIT_ENTRY is required as a swap entry, we need to
        // ask the fault handler to wait until we should continue.  Rathern
        // than recopy this boilerplate code everywhere, we just ask them
        // to wait.
        MmUnlockSectionSegment(Segment);
        return STATUS_SUCCESS + 1;
    }
    else if (Entry)
    {
        PFN_NUMBER Page = PFN_FROM_SSE(Entry);
        DPRINT("Take reference to page %x #\n", Page);

        if (MiGetPfnEntry(Page) == NULL)
        {
            DPRINT1("Found no PFN entry for page 0x%x in page entry 0x%x (segment: 0x%p, offset: %08x%08x)\n",
                    Page,
                    Entry,
                    Segment,
                    TotalOffset.HighPart,
                    TotalOffset.LowPart);
            KeBugCheck(CACHE_MANAGER);
        }

        OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
        MmReferencePage(Page);
        KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);

        Status = MmCreateVirtualMapping(Process, Address, Attributes, &Page, 1);
        if (NT_SUCCESS(Status))
        {
            MmInsertRmap(Page, Process, Address);
        }
        DPRINT("XXX Set Event %x\n", Status);
        MiSetPageEvent(Process, Address);
        MmUnlockSectionSegment(Segment);
        DPRINT("Status %x\n", Status);
        return Status;
    }
    else
    {
        DPRINT("Get page into section\n");
        /*
         * If the entry is zero (and it can't change because we have
         * locked the segment) then we need to load the page.
         */
        //DPRINT1("Read from file %08x %wZ\n", FileOffset.LowPart, &Section->FileObject->FileName);
        Required->State = 2;
        Required->Context = Segment->FileObject;
        Required->Consumer = Consumer;
        Required->FileOffset = FileOffset;
        Required->Amount = PAGE_SIZE;
        Required->DoAcquisition = MiReadFilePage;

        MmSetPageEntrySectionSegment(Segment,
                                     &TotalOffset,
                                     MAKE_SWAP_SSE(MM_WAIT_ENTRY));

        MmUnlockSectionSegment(Segment);
        return STATUS_MORE_PROCESSING_REQUIRED;
    }
    ASSERT(FALSE);
    return STATUS_ACCESS_VIOLATION;
}
示例#10
0
文件: swapout.c 项目: RPG-7/reactos
NTSTATUS
NTAPI
MmpPageOutPhysicalAddress(PFN_NUMBER Page)
{
    BOOLEAN ProcRef = FALSE, PageDirty;
    PFN_NUMBER SectionPage = 0;
    PMM_RMAP_ENTRY entry;
    PMM_SECTION_SEGMENT Segment = NULL;
    LARGE_INTEGER FileOffset;
    PMEMORY_AREA MemoryArea;
    PMMSUPPORT AddressSpace = NULL;
    BOOLEAN Dirty = FALSE;
    PVOID Address = NULL;
    PEPROCESS Process = NULL;
    NTSTATUS Status = STATUS_SUCCESS;
    MM_REQUIRED_RESOURCES Resources = { 0 };

    DPRINTC("Page out %x (ref ct %x)\n", Page, MmGetReferenceCountPage(Page));

    ExAcquireFastMutex(&MiGlobalPageOperation);
    if ((Segment = MmGetSectionAssociation(Page, &FileOffset)))
    {
        DPRINTC("Withdrawing page (%x) %p:%x\n",
                Page,
                Segment,
                FileOffset.LowPart);

        SectionPage = MmWithdrawSectionPage(Segment, &FileOffset, &Dirty);
        DPRINTC("SectionPage %x\n", SectionPage);

        if (SectionPage == MM_WAIT_ENTRY || SectionPage == 0)
        {
            DPRINT1("In progress page out %x\n", SectionPage);
            ExReleaseFastMutex(&MiGlobalPageOperation);
            return STATUS_UNSUCCESSFUL;
        }
        else
        {
            ASSERT(SectionPage == Page);
        }
        Resources.State = Dirty ? 1 : 0;
    }
    else
    {
        DPRINT("No segment association for %x\n", Page);
    }

    Dirty = MmIsDirtyPageRmap(Page);

    DPRINTC("Trying to unmap all instances of %x\n", Page);
    ExAcquireFastMutex(&RmapListLock);
    entry = MmGetRmapListHeadPage(Page);

    // Entry and Segment might be null here in the case that the page
    // is new and is in the process of being swapped in
    if (!entry && !Segment)
    {
        Status = STATUS_UNSUCCESSFUL;
        DPRINT1("Page %x is in transit\n", Page);
        ExReleaseFastMutex(&RmapListLock);
        goto bail;
    }

    while (entry != NULL && NT_SUCCESS(Status))
    {
        Process = entry->Process;
        Address = entry->Address;

        DPRINTC("Process %p Address %p Page %x\n", Process, Address, Page);

        if (RMAP_IS_SEGMENT(Address))
        {
            entry = entry->Next;
            continue;
        }

        if (Process && Address < MmSystemRangeStart)
        {
            /* Make sure we don't try to page out part of an exiting process */
            if (PspIsProcessExiting(Process))
            {
                DPRINT("bail\n");
                ExReleaseFastMutex(&RmapListLock);
                goto bail;
            }
            ObReferenceObject(Process);
            ProcRef = TRUE;
            AddressSpace = &Process->Vm;
        }
        else
        {
            AddressSpace = MmGetKernelAddressSpace();
        }
        ExReleaseFastMutex(&RmapListLock);

        RtlZeroMemory(&Resources, sizeof(Resources));

        if ((((ULONG_PTR)Address) & 0xFFF) != 0)
        {
            KeBugCheck(MEMORY_MANAGEMENT);
        }

        do
        {
            MmLockAddressSpace(AddressSpace);

            MemoryArea = MmLocateMemoryAreaByAddress(AddressSpace, Address);
            if (MemoryArea == NULL || MemoryArea->DeleteInProgress)
            {
                Status = STATUS_UNSUCCESSFUL;
                MmUnlockAddressSpace(AddressSpace);
                DPRINTC("bail\n");
                goto bail;
            }

            DPRINTC("Type %x (%p -> %p)\n",
                    MemoryArea->Type,
                    MemoryArea->StartingAddress,
                    MemoryArea->EndingAddress);

            Resources.DoAcquisition = NULL;
            Resources.Page[0] = Page;

            ASSERT(KeGetCurrentIrql() <= APC_LEVEL);

            DPRINT("%p:%p, page %x %x\n",
                   Process,
                   Address,
                   Page,
                   Resources.Page[0]);

            PageDirty = FALSE;

            Status = MmPageOutCacheSection(AddressSpace,
                                           MemoryArea,
                                           Address,
                                           &PageDirty,
                                           &Resources);

            Dirty |= PageDirty;
            DPRINT("%x\n", Status);

            ASSERT(KeGetCurrentIrql() <= APC_LEVEL);

            MmUnlockAddressSpace(AddressSpace);

            if (Status == STATUS_SUCCESS + 1)
            {
                // Wait page ... the other guy has it, so we'll just fail for now
                DPRINT1("Wait entry ... can't continue\n");
                Status = STATUS_UNSUCCESSFUL;
                goto bail;
            }
            else if (Status == STATUS_MORE_PROCESSING_REQUIRED)
            {
                DPRINTC("DoAcquisition %p\n", Resources.DoAcquisition);

                Status = Resources.DoAcquisition(AddressSpace,
                                                 MemoryArea,
                                                 &Resources);

                DPRINTC("Status %x\n", Status);
                if (!NT_SUCCESS(Status))
                {
                    DPRINT1("bail\n");
                    goto bail;
                }
                else
                {
                    Status = STATUS_MM_RESTART_OPERATION;
                }
            }
        }
        while (Status == STATUS_MM_RESTART_OPERATION);

        if (ProcRef)
        {
            ObDereferenceObject(Process);
            ProcRef = FALSE;
        }

        ExAcquireFastMutex(&RmapListLock);
        ASSERT(!MM_IS_WAIT_PTE(MmGetPfnForProcess(Process, Address)));
        entry = MmGetRmapListHeadPage(Page);

        DPRINTC("Entry %p\n", entry);
    }

    ExReleaseFastMutex(&RmapListLock);

bail:
    DPRINTC("BAIL %x\n", Status);

    if (Segment)
    {
        ULONG RefCount;

        DPRINTC("About to finalize section page %x (%p:%x) Status %x %s\n",
                Page,
                Segment,
                FileOffset.LowPart,
                Status,
                Dirty ? "dirty" : "clean");

        if (!NT_SUCCESS(Status) ||
            !NT_SUCCESS(Status = MmFinalizeSectionPageOut(Segment,
                                                          &FileOffset,
                                                          Page,
                                                          Dirty)))
        {
            DPRINTC("Failed to page out %x, replacing %x at %x in segment %x\n",
                    SectionPage,
                    FileOffset.LowPart,
                    Segment);

            MmLockSectionSegment(Segment);

            MmSetPageEntrySectionSegment(Segment,
                                         &FileOffset,
                                         Dirty ? MAKE_PFN_SSE(Page) : DIRTY_SSE(MAKE_PFN_SSE(Page)));

            MmUnlockSectionSegment(Segment);
        }

        /* Alas, we had the last reference */
        if ((RefCount = InterlockedDecrementUL(&Segment->ReferenceCount)) == 0)
            MmFinalizeSegment(Segment);
    }

    if (ProcRef)
    {
        DPRINTC("Dereferencing process...\n");
        ObDereferenceObject(Process);
    }

    ExReleaseFastMutex(&MiGlobalPageOperation);

    DPRINTC("%s %x %x\n",
            NT_SUCCESS(Status) ? "Evicted" : "Spared",
            Page,
            Status);

    return NT_SUCCESS(Status) ? STATUS_SUCCESS : STATUS_UNSUCCESSFUL;
}
示例#11
0
NTSTATUS
NTAPI
MiReadFilePage(PMMSUPPORT AddressSpace,
               PMEMORY_AREA MemoryArea,
               PMM_REQUIRED_RESOURCES RequiredResources)
{
    PFILE_OBJECT FileObject = RequiredResources->Context;
    PPFN_NUMBER Page = &RequiredResources->Page[RequiredResources->Offset];
    PLARGE_INTEGER FileOffset = &RequiredResources->FileOffset;
    NTSTATUS Status;
    PVOID PageBuf = NULL;
    KEVENT Event;
    IO_STATUS_BLOCK IOSB;
    UCHAR MdlBase[sizeof(MDL) + sizeof(ULONG)];
    PMDL Mdl = (PMDL)MdlBase;
    KIRQL OldIrql;

    DPRINTC("Pulling page %I64x from %wZ to %Ix\n",
            FileOffset->QuadPart,
            &FileObject->FileName,
            *Page);

    Status = MmRequestPageMemoryConsumer(RequiredResources->Consumer,
                                         TRUE,
                                         Page);

    if (!NT_SUCCESS(Status))
    {
        DPRINT1("Status: %x\n", Status);
        return Status;
    }

    MmInitializeMdl(Mdl, NULL, PAGE_SIZE);
    MmBuildMdlFromPages(Mdl, Page);
    Mdl->MdlFlags |= MDL_PAGES_LOCKED;

    KeInitializeEvent(&Event, NotificationEvent, FALSE);
    Status = IoPageRead(FileObject, Mdl, FileOffset, &Event, &IOSB);
    if (Status == STATUS_PENDING)
    {
        KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
        Status = IOSB.Status;
    }
    if (Mdl->MdlFlags & MDL_MAPPED_TO_SYSTEM_VA)
    {
        MmUnmapLockedPages (Mdl->MappedSystemVa, Mdl);
    }

    PageBuf = MiMapPageInHyperSpace(PsGetCurrentProcess(), *Page, &OldIrql);
    if (!PageBuf)
    {
        MmReleasePageMemoryConsumer(RequiredResources->Consumer, *Page);
        return STATUS_NO_MEMORY;
    }

    RtlZeroMemory((PCHAR)PageBuf+RequiredResources->Amount,
                  PAGE_SIZE-RequiredResources->Amount);

    MiUnmapPageInHyperSpace(PsGetCurrentProcess(), PageBuf, OldIrql);

    DPRINT("Read Status %x (Page %x)\n", Status, *Page);

    if (!NT_SUCCESS(Status))
    {
        MmReleasePageMemoryConsumer(RequiredResources->Consumer, *Page);
        DPRINT("Status: %x\n", Status);
        return Status;
    }

    return STATUS_SUCCESS;
}