VOID NTAPI HalpUnmapRealModeMemory(VOID) { ULONG i; PHARDWARE_PTE Pte; // // Loop the first meg of memory // for (i = 0; i < 0x100000; i += PAGE_SIZE) { // // Invalidate each PTE // Pte = HalAddressToPte(i); Pte->Valid = 0; Pte->Write = 0; Pte->Owner = 0; Pte->PageFrameNumber = 0; } // // Restore the PDE for the lowest megabyte of memory // Pte = HalAddressToPde(0); *Pte = HalpSavedPte; Pte->PageFrameNumber = HalpSavedPfn; // // Flush the TLB // HalpFlushTLB(); }
VOID NTAPI HalpUnmapVirtualAddressVista(IN PVOID VirtualAddress, IN PFN_COUNT PageCount, IN BOOLEAN FlushCurrentTLB) { PHARDWARE_PTE PointerPte; ULONG i; /* Only accept valid addresses */ if (VirtualAddress < (PVOID)MM_HAL_VA_START) return; /* Align it down to page size */ VirtualAddress = (PVOID)((ULONG_PTR)VirtualAddress & ~(PAGE_SIZE - 1)); /* Loop PTEs */ PointerPte = HalAddressToPte(VirtualAddress); for (i = 0; i < PageCount; i++) { *(PULONG)PointerPte = 0; PointerPte++; } /* Flush the TLB */ if (FlushCurrentTLB) HalpFlushTLB(); /* Put the heap back */ if (HalpHeapStart > VirtualAddress) HalpHeapStart = VirtualAddress; }
VOID NTAPI ApicInitializeIOApic(VOID) { PHARDWARE_PTE Pte; IOAPIC_REDIRECTION_REGISTER ReDirReg; UCHAR Index; ULONG Vector; /* Map the I/O Apic page */ Pte = HalAddressToPte(IOAPIC_BASE); Pte->PageFrameNumber = IOAPIC_PHYS_BASE / PAGE_SIZE; Pte->Valid = 1; Pte->Write = 1; Pte->Owner = 1; Pte->CacheDisable = 1; Pte->Global = 1; _ReadWriteBarrier(); /* Setup a redirection entry */ ReDirReg.Vector = 0xFF; ReDirReg.DeliveryMode = APIC_MT_Fixed; ReDirReg.DestinationMode = APIC_DM_Physical; ReDirReg.DeliveryStatus = 0; ReDirReg.Polarity = 0; ReDirReg.RemoteIRR = 0; ReDirReg.TriggerMode = APIC_TGM_Edge; ReDirReg.Mask = 1; ReDirReg.Reserved = 0; ReDirReg.Destination = 0; /* Loop all table entries */ for (Index = 0; Index < 24; Index++) { /* Initialize entry */ IOApicWrite(IOAPIC_REDTBL + 2 * Index, ReDirReg.Long0); IOApicWrite(IOAPIC_REDTBL + 2 * Index + 1, ReDirReg.Long1); } /* Init the vactor to index table */ for (Vector = 0; Vector <= 255; Vector++) { HalpVectorToIndex[Vector] = 0xFF; } // HACK: Allocate all IRQs, should rather do that on demand for (Index = 0; Index <= 15; Index++) { /* Map the IRQs to IRQLs like with the PIC */ HalpAllocateSystemInterrupt(Index, 27 - Index); } /* Enable the timer interrupt */ ReDirReg.Vector = APIC_CLOCK_VECTOR; ReDirReg.DeliveryMode = APIC_MT_Fixed; ReDirReg.DestinationMode = APIC_DM_Physical; ReDirReg.TriggerMode = APIC_TGM_Edge; ReDirReg.Mask = 0; ReDirReg.Destination = ApicRead(APIC_ID); IOApicWrite(IOAPIC_REDTBL + 2 * APIC_CLOCK_INDEX, ReDirReg.Long0); ApicSendEOI(); }
BOOLEAN NTAPI HalpBiosDisplayReset(VOID) { ULONG Flags; PHARDWARE_PTE IdtPte; BOOLEAN RestoreWriteProtection = FALSE; // // Disable interrupts // Flags = __readeflags(); _disable(); // // Map memory available to the V8086 real-mode code // HalpMapRealModeMemory(); // // On P5, the first 7 entries of the IDT are write protected to work around // the cmpxchg8b lock errata. Unprotect them here so we can set our custom // invalid op-code handler. // IdtPte = HalAddressToPte(((PKIPCR)KeGetPcr())->IDT); RestoreWriteProtection = IdtPte->Write != 0; IdtPte->Write = 1; // // Use special invalid opcode and GPF trap handlers // HalpSwitchToRealModeTrapHandlers(); // // Configure the IOPM and TSS // HalpSetupRealModeIoPermissionsAndTask(); // // Now jump to real mode // HalpBiosCall(); // // Restore kernel trap handlers // HalpRestoreTrapHandlers(); // // Restore write permission // IdtPte->Write = RestoreWriteProtection; // // Restore TSS and IOPM // HalpRestoreIoPermissionsAndTask(); // // Restore low memory mapping // HalpUnmapRealModeMemory(); // // Restore interrupts if they were previously enabled // __writeeflags(Flags); return TRUE; }
VOID NTAPI HalpMapRealModeMemory(VOID) { PHARDWARE_PTE Pte, V86Pte; ULONG i; // // Get the page table directory for the lowest meg of memory // Pte = HalAddressToPde(0); HalpSavedPfn = Pte->PageFrameNumber; HalpSavedPte = *Pte; // // Map it to the HAL reserved region and make it valid // Pte->Valid = 1; Pte->Write = 1; Pte->Owner = 1; Pte->PageFrameNumber = (HalAddressToPde(0xFFC00000))->PageFrameNumber; // // Flush the TLB // HalpFlushTLB(); // // Now loop the first meg of memory // for (i = 0; i < 0x100000; i += PAGE_SIZE) { // // Identity map it // Pte = HalAddressToPte(i); Pte->PageFrameNumber = i >> PAGE_SHIFT; Pte->Valid = 1; Pte->Write = 1; Pte->Owner = 1; } // // Now get the entry for our real mode V86 code and the target // Pte = HalAddressToPte(0x20000); V86Pte = HalAddressToPte(&HalpRealModeStart); do { // // Map the physical address into our real-mode region // Pte->PageFrameNumber = V86Pte->PageFrameNumber; // // Keep going until we've reached the end of our region // Pte++; V86Pte++; } while (V86Pte <= HalAddressToPte(&HalpRealModeEnd)); // // Flush the TLB // HalpFlushTLB(); }
PVOID NTAPI HalpMapPhysicalMemory64Vista(IN PHYSICAL_ADDRESS PhysicalAddress, IN PFN_COUNT PageCount, IN BOOLEAN FlushCurrentTLB) { PHARDWARE_PTE PointerPte; PFN_NUMBER UsedPages = 0; PVOID VirtualAddress, BaseAddress; /* Start at the current HAL heap base */ BaseAddress = HalpHeapStart; VirtualAddress = BaseAddress; /* Loop until we have all the pages required */ while (UsedPages < PageCount) { /* If this overflows past the HAL heap, it means there's no space */ if (VirtualAddress == NULL) return NULL; /* Get the PTE for this address */ PointerPte = HalAddressToPte(VirtualAddress); /* Go to the next page */ VirtualAddress = (PVOID)((ULONG_PTR)VirtualAddress + PAGE_SIZE); /* Check if the page is available */ if (PointerPte->Valid) { /* PTE has data, skip it and start with a new base address */ BaseAddress = VirtualAddress; UsedPages = 0; continue; } /* PTE is available, keep going on this run */ UsedPages++; } /* Take the base address of the page plus the actual offset in the address */ VirtualAddress = (PVOID)((ULONG_PTR)BaseAddress + BYTE_OFFSET(PhysicalAddress.LowPart)); /* If we are starting at the heap, move the heap */ if (BaseAddress == HalpHeapStart) { /* Past this allocation */ HalpHeapStart = (PVOID)((ULONG_PTR)BaseAddress + (PageCount * PAGE_SIZE)); } /* Loop pages that can be mapped */ while (UsedPages--) { /* Fill out the PTE */ PointerPte = HalAddressToPte(BaseAddress); PointerPte->PageFrameNumber = (PFN_NUMBER)(PhysicalAddress.QuadPart >> PAGE_SHIFT); PointerPte->Valid = 1; PointerPte->Write = 1; /* Move to the next address */ PhysicalAddress.QuadPart += PAGE_SIZE; BaseAddress = (PVOID)((ULONG_PTR)BaseAddress + PAGE_SIZE); } /* Flush the TLB and return the address */ if (FlushCurrentTLB) HalpFlushTLB(); return VirtualAddress; }