mirror of https://gitlab.com/nakst/essence
				
				
				
			kernel cleanup 2
This commit is contained in:
		
							parent
							
								
									6fa375a9d8
								
							
						
					
					
						commit
						7a0b832c36
					
				
							
								
								
									
										1042
									
								
								drivers/acpi.cpp
								
								
								
								
							
							
						
						
									
										1042
									
								
								drivers/acpi.cpp
								
								
								
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							|  | @ -0,0 +1,637 @@ | ||||||
|  | // TODO Warning: Not all of the OSL has been tested.
 | ||||||
|  | 
 | ||||||
|  | extern "C"  { | ||||||
|  | #pragma GCC diagnostic ignored "-Wunused-parameter" push | ||||||
|  | #include <ports/acpica/include/acpi.h> | ||||||
|  | #pragma GCC diagnostic pop | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | struct ACPICAEvent { | ||||||
|  | 	ACPI_OSD_EXEC_CALLBACK function; | ||||||
|  | 	void *context; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | // TODO Can these arrays be made smaller?
 | ||||||
|  | Thread *acpiEvents[256]; | ||||||
|  | size_t acpiEventCount; | ||||||
|  | ACPI_OSD_HANDLER acpiInterruptHandlers[256]; | ||||||
|  | void *acpiInterruptContexts[256]; | ||||||
|  | uint8_t acpicaPageBuffer[K_PAGE_SIZE]; | ||||||
|  | KMutex acpicaPageBufferMutex; | ||||||
|  | char acpiPrintf[4096]; | ||||||
|  | bool acpiOSLayerActive = false; | ||||||
|  | 
 | ||||||
|  | ES_EXTERN_C ACPI_STATUS AcpiOsInitialize() { | ||||||
|  | 	if (acpiOSLayerActive) KernelPanic("AcpiOsInitialize - ACPI has already been initialised.\n"); | ||||||
|  | 	acpiOSLayerActive = true; | ||||||
|  | 	KernelLog(LOG_INFO, "ACPI", "initialise ACPICA", "AcpiOsInitialize - Initialising ACPICA OS layer...\n"); | ||||||
|  | 	return AE_OK; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | ES_EXTERN_C ACPI_STATUS AcpiOsTerminate() { | ||||||
|  | 	if (!acpiOSLayerActive) KernelPanic("AcpiOsTerminate - ACPI has not been initialised.\n"); | ||||||
|  | 	acpiOSLayerActive = false; | ||||||
|  | 	KernelLog(LOG_INFO, "ACPI", "terminate ACPICA", "AcpiOsTerminate - Terminating ACPICA OS layer...\n"); | ||||||
|  | 	return AE_OK; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | ES_EXTERN_C ACPI_PHYSICAL_ADDRESS AcpiOsGetRootPointer() { | ||||||
|  | 	ACPI_PHYSICAL_ADDRESS address = 0; | ||||||
|  | 
 | ||||||
|  | 	uint64_t uefiRSDP = *((uint64_t *) (LOW_MEMORY_MAP_START + GetBootloaderInformationOffset() + 0x7FE8)); | ||||||
|  | 
 | ||||||
|  | 	if (uefiRSDP) { | ||||||
|  | 		return uefiRSDP; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	AcpiFindRootPointer(&address); | ||||||
|  | 	return address; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | ES_EXTERN_C ACPI_STATUS AcpiOsPredefinedOverride(const ACPI_PREDEFINED_NAMES *predefinedObject, ACPI_STRING *newValue) { | ||||||
|  | 	(void) predefinedObject; | ||||||
|  | 	*newValue = nullptr; | ||||||
|  | 	return AE_OK; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | ES_EXTERN_C ACPI_STATUS AcpiOsTableOverride(ACPI_TABLE_HEADER *existingTable, ACPI_TABLE_HEADER **newTable) { | ||||||
|  | 	(void) existingTable; | ||||||
|  | 	*newTable = nullptr; | ||||||
|  | 	return AE_OK; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | ES_EXTERN_C ACPI_STATUS AcpiOsPhysicalTableOverride(ACPI_TABLE_HEADER *existingTable, ACPI_PHYSICAL_ADDRESS *newAddress, uint32_t *newTableLength) { | ||||||
|  | 	(void) existingTable; | ||||||
|  | 	*newAddress = 0; | ||||||
|  | 	*newTableLength = 0; | ||||||
|  | 	return AE_OK; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | ES_EXTERN_C void *AcpiOsMapMemory(ACPI_PHYSICAL_ADDRESS physicalAddress, ACPI_SIZE length) { | ||||||
|  | 	return ACPIMapPhysicalMemory(physicalAddress, length); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | ES_EXTERN_C void AcpiOsUnmapMemory(void *address, ACPI_SIZE length) { | ||||||
|  | #ifdef ARCH_X86_COMMON | ||||||
|  | 	if ((uintptr_t) address - (uintptr_t) LOW_MEMORY_MAP_START < (uintptr_t) LOW_MEMORY_LIMIT) { | ||||||
|  | 		return; | ||||||
|  | 	} | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|  | 	(void) length; | ||||||
|  | 	MMFree(kernelMMSpace, address); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | ES_EXTERN_C ACPI_STATUS AcpiOsGetPhysicalAddress(void *virtualAddress, ACPI_PHYSICAL_ADDRESS *physicalAddress) { | ||||||
|  | 	if (!virtualAddress || !physicalAddress) { | ||||||
|  | 		return AE_BAD_PARAMETER; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	*physicalAddress = MMArchTranslateAddress(kernelMMSpace, (uintptr_t) virtualAddress); | ||||||
|  | 	return AE_OK; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | ES_EXTERN_C void *AcpiOsAllocate(ACPI_SIZE size) { | ||||||
|  | 	return EsHeapAllocate(size, false, K_FIXED); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | ES_EXTERN_C void AcpiOsFree(void *memory) { | ||||||
|  | 	EsHeapFree(memory, 0, K_FIXED); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | ES_EXTERN_C BOOLEAN AcpiOsReadable(void *memory, ACPI_SIZE length) { | ||||||
|  | 	(void) memory; | ||||||
|  | 	(void) length; | ||||||
|  | 	// This is only used by the debugger, which we don't use...
 | ||||||
|  | 	return TRUE; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | ES_EXTERN_C BOOLEAN AcpiOsWritable(void *memory, ACPI_SIZE length) { | ||||||
|  | 	(void) memory; | ||||||
|  | 	(void) length; | ||||||
|  | 	// This is only used by the debugger, which we don't use...
 | ||||||
|  | 	return TRUE; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | ES_EXTERN_C ACPI_THREAD_ID AcpiOsGetThreadId() { | ||||||
|  | 	return GetCurrentThread()->id + 1; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void RunACPICAEvent(void *e) { | ||||||
|  | 	ACPICAEvent *event = (ACPICAEvent *) e; | ||||||
|  | 	event->function(event->context); | ||||||
|  | 	EsHeapFree(event, 0, K_FIXED); | ||||||
|  | 	scheduler.TerminateThread(GetCurrentThread()); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | ES_EXTERN_C ACPI_STATUS AcpiOsExecute(ACPI_EXECUTE_TYPE type, ACPI_OSD_EXEC_CALLBACK function, void *context) { | ||||||
|  | 	(void) type; | ||||||
|  | 
 | ||||||
|  | 	if (!function) return AE_BAD_PARAMETER; | ||||||
|  | 
 | ||||||
|  | 	ACPICAEvent *event = (ACPICAEvent *) EsHeapAllocate(sizeof(ACPICAEvent), true, K_FIXED); | ||||||
|  | 	event->function = function; | ||||||
|  | 	event->context = context; | ||||||
|  | 
 | ||||||
|  | 	Thread *thread = scheduler.SpawnThread("ACPICAEvent", (uintptr_t) RunACPICAEvent, (uintptr_t) event); | ||||||
|  | 
 | ||||||
|  | 	if (acpiEventCount == 256) { | ||||||
|  | 		KernelPanic("AcpiOsExecute - Exceeded maximum event count, 256.\n"); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if (thread) { | ||||||
|  | 		acpiEvents[acpiEventCount++] = thread; | ||||||
|  | 		return AE_OK; | ||||||
|  | 	} else { | ||||||
|  | 		return AE_NO_MEMORY; | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | ES_EXTERN_C void AcpiOsSleep(UINT64 ms) { | ||||||
|  | 	KEvent event = {}; | ||||||
|  | 	KEventWait(&event, ms); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | ES_EXTERN_C void AcpiOsStall(UINT32 mcs) { | ||||||
|  | 	(void) mcs; | ||||||
|  | 	uint64_t start = ProcessorReadTimeStamp(); | ||||||
|  | 	uint64_t end = start + mcs * (timeStampTicksPerMs / 1000); | ||||||
|  | 	while (ProcessorReadTimeStamp() < end); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | ES_EXTERN_C void AcpiOsWaitEventsComplete() { | ||||||
|  | 	for (uintptr_t i = 0; i < acpiEventCount; i++) { | ||||||
|  | 		Thread *thread = acpiEvents[i]; | ||||||
|  | 		KEventWait(&thread->killedEvent, ES_WAIT_NO_TIMEOUT); | ||||||
|  | 		CloseHandleToObject(thread, KERNEL_OBJECT_THREAD); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	acpiEventCount = 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | ES_EXTERN_C ACPI_STATUS AcpiOsCreateSemaphore(UINT32 maxUnits, UINT32 initialUnits, ACPI_SEMAPHORE *handle) { | ||||||
|  | 	if (!handle) return AE_BAD_PARAMETER; | ||||||
|  | 
 | ||||||
|  | 	KSemaphore *semaphore = (KSemaphore *) EsHeapAllocate(sizeof(KSemaphore), true, K_FIXED); | ||||||
|  | 	KSemaphoreReturn(semaphore, initialUnits); | ||||||
|  | 	semaphore->_custom = maxUnits; | ||||||
|  | 	*handle = semaphore; | ||||||
|  | 	return AE_OK; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | ES_EXTERN_C ACPI_STATUS AcpiOsDeleteSemaphore(ACPI_SEMAPHORE handle) { | ||||||
|  | 	if (!handle) return AE_BAD_PARAMETER; | ||||||
|  | 	EsHeapFree(handle, sizeof(KSemaphore), K_FIXED); | ||||||
|  | 	return AE_OK; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | ES_EXTERN_C ACPI_STATUS AcpiOsWaitSemaphore(ACPI_SEMAPHORE handle, UINT32 units, UINT16 timeout) { | ||||||
|  | 	(void) timeout; | ||||||
|  | 	if (!handle) return AE_BAD_PARAMETER; | ||||||
|  | 	KSemaphore *semaphore = (KSemaphore *) handle; | ||||||
|  | 
 | ||||||
|  | 	if (KSemaphoreTake(semaphore, units, timeout == (UINT16) -1 ? ES_WAIT_NO_TIMEOUT : timeout)) { | ||||||
|  | 		return AE_OK; | ||||||
|  | 	} else { | ||||||
|  | 		return AE_TIME; | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | ES_EXTERN_C ACPI_STATUS AcpiOsSignalSemaphore(ACPI_SEMAPHORE handle, UINT32 units) { | ||||||
|  | 	if (!handle) return AE_BAD_PARAMETER; | ||||||
|  | 	KSemaphore *semaphore = (KSemaphore *) handle; | ||||||
|  | 	if (semaphore->units + units > semaphore->_custom) return AE_LIMIT; | ||||||
|  | 	KSemaphoreReturn(semaphore, units); | ||||||
|  | 	return AE_OK; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | ES_EXTERN_C ACPI_STATUS AcpiOsCreateLock(ACPI_SPINLOCK *handle) { | ||||||
|  | 	if (!handle) return AE_BAD_PARAMETER; | ||||||
|  | 	KSpinlock *spinlock = (KSpinlock *) EsHeapAllocate(sizeof(KSpinlock), true, K_FIXED); | ||||||
|  | 	*handle = spinlock; | ||||||
|  | 	return AE_OK; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | ES_EXTERN_C void AcpiOsDeleteLock(ACPI_HANDLE handle) { | ||||||
|  | 	EsHeapFree(handle, sizeof(KSpinlock), K_FIXED); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | ES_EXTERN_C ACPI_CPU_FLAGS AcpiOsAcquireLock(ACPI_SPINLOCK handle) { | ||||||
|  | 	KSpinlock *spinlock = (KSpinlock *) handle; | ||||||
|  | 	KSpinlockAcquire(spinlock); | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | ES_EXTERN_C void AcpiOsReleaseLock(ACPI_SPINLOCK handle, ACPI_CPU_FLAGS flags) { | ||||||
|  | 	(void) flags; | ||||||
|  | 	KSpinlock *spinlock = (KSpinlock *) handle; | ||||||
|  | 	KSpinlockRelease(spinlock); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | bool ACPIInterrupt(uintptr_t interruptIndex, void *) { | ||||||
|  | 	if (acpiInterruptHandlers[interruptIndex]) { | ||||||
|  | 		return ACPI_INTERRUPT_HANDLED == acpiInterruptHandlers[interruptIndex](acpiInterruptContexts[interruptIndex]); | ||||||
|  | 	} else { | ||||||
|  | 		return false; | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | ES_EXTERN_C ACPI_STATUS AcpiOsInstallInterruptHandler(UINT32 interruptLevel, ACPI_OSD_HANDLER handler, void *context) { | ||||||
|  | 	if (interruptLevel > 256 || !handler) return AE_BAD_PARAMETER; | ||||||
|  | 	 | ||||||
|  | 	if (acpiInterruptHandlers[interruptLevel]) { | ||||||
|  | 		return AE_ALREADY_EXISTS; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	acpiInterruptHandlers[interruptLevel] = handler; | ||||||
|  | 	acpiInterruptContexts[interruptLevel] = context; | ||||||
|  | 
 | ||||||
|  | 	return KRegisterIRQ(interruptLevel, ACPIInterrupt, nullptr, "ACPICA") ? AE_OK : AE_ERROR; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | ES_EXTERN_C ACPI_STATUS AcpiOsRemoveInterruptHandler(UINT32 interruptNumber, ACPI_OSD_HANDLER handler) { | ||||||
|  | 	if (interruptNumber > 256 || !handler) return AE_BAD_PARAMETER; | ||||||
|  | 
 | ||||||
|  | 	if (!acpiInterruptHandlers[interruptNumber]) { | ||||||
|  | 		return AE_NOT_EXIST; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if (handler != acpiInterruptHandlers[interruptNumber]) { | ||||||
|  | 		return AE_BAD_PARAMETER; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	acpiInterruptHandlers[interruptNumber] = nullptr; | ||||||
|  | 
 | ||||||
|  | 	return AE_OK; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | ES_EXTERN_C ACPI_STATUS AcpiOsReadMemory(ACPI_PHYSICAL_ADDRESS address, UINT64 *value, UINT32 width) { | ||||||
|  | 	KMutexAcquire(&acpicaPageBufferMutex); | ||||||
|  | 	EsDefer(KMutexRelease(&acpicaPageBufferMutex)); | ||||||
|  | 
 | ||||||
|  | 	uintptr_t page = (uintptr_t) address & ~(K_PAGE_SIZE - 1); | ||||||
|  | 	uintptr_t offset = (uintptr_t) address & (K_PAGE_SIZE - 1); | ||||||
|  | 
 | ||||||
|  | 	PMRead(page, acpicaPageBuffer, 1); | ||||||
|  | 	 | ||||||
|  | 	if (width == 64) { | ||||||
|  | 		*value = *((uint64_t *) (acpicaPageBuffer + offset)); | ||||||
|  | 	} else if (width == 32) { | ||||||
|  | 		*value = *((uint32_t *) (acpicaPageBuffer + offset)); | ||||||
|  | 	} else if (width == 16) { | ||||||
|  | 		*value = *((uint16_t *) (acpicaPageBuffer + offset)); | ||||||
|  | 	} else { | ||||||
|  | 		*value = acpicaPageBuffer[offset]; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return AE_OK; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | ES_EXTERN_C ACPI_STATUS AcpiOsWriteMemory(ACPI_PHYSICAL_ADDRESS address, UINT64 value, UINT32 width) { | ||||||
|  | 	KMutexAcquire(&acpicaPageBufferMutex); | ||||||
|  | 	EsDefer(KMutexRelease(&acpicaPageBufferMutex)); | ||||||
|  | 
 | ||||||
|  | 	uintptr_t page = (uintptr_t) address & ~(K_PAGE_SIZE - 1); | ||||||
|  | 	uintptr_t offset = (uintptr_t) address & (K_PAGE_SIZE - 1); | ||||||
|  | 
 | ||||||
|  | 	PMRead(page, acpicaPageBuffer, 1); | ||||||
|  | 	 | ||||||
|  | 	if (width == 64) { | ||||||
|  | 		*((uint64_t *) (acpicaPageBuffer + offset)) = value; | ||||||
|  | 	} else if (width == 32) { | ||||||
|  | 		*((uint32_t *) (acpicaPageBuffer + offset)) = value; | ||||||
|  | 	} else if (width == 16) { | ||||||
|  | 		*((uint16_t *) (acpicaPageBuffer + offset)) = value; | ||||||
|  | 	} else { | ||||||
|  | 		*((uint8_t *) (acpicaPageBuffer + offset)) = value; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	PMCopy(page, acpicaPageBuffer, 1); | ||||||
|  | 
 | ||||||
|  | 	return AE_OK; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | ES_EXTERN_C ACPI_STATUS AcpiOsReadPort(ACPI_IO_ADDRESS address, UINT32 *value, UINT32 width) { | ||||||
|  | 	// EsPrint("AcpiOsReadPort - %x, %d", address, width);
 | ||||||
|  | 		 | ||||||
|  | 	if (width == 8) { | ||||||
|  | 		*value = ProcessorIn8(address); | ||||||
|  | 	} else if (width == 16) { | ||||||
|  | 		*value = ProcessorIn16(address); | ||||||
|  | 	} else if (width == 32) { | ||||||
|  | 		*value = ProcessorIn32(address); | ||||||
|  | 	} else { | ||||||
|  | 		return AE_ERROR; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	// EsPrint(" - %x\n", *value);
 | ||||||
|  | 
 | ||||||
|  | 	return AE_OK; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | ES_EXTERN_C ACPI_STATUS AcpiOsWritePort(ACPI_IO_ADDRESS address, UINT32 value, UINT32 width) { | ||||||
|  | 	// EsPrint("AcpiOsWritePort - %x, %x, %d", address, value, width);
 | ||||||
|  | 
 | ||||||
|  | 	if (width == 8) { | ||||||
|  | 		ProcessorOut8(address, (uint8_t) value); | ||||||
|  | 	} else if (width == 16) { | ||||||
|  | 		ProcessorOut16(address, (uint16_t) value); | ||||||
|  | 	} else if (width == 32) { | ||||||
|  | 		ProcessorOut32(address, (uint32_t) value); | ||||||
|  | 	} else { | ||||||
|  | 		return AE_ERROR; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	// EsPrint(" - ;;\n");
 | ||||||
|  | 
 | ||||||
|  | 	return AE_OK; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | ES_EXTERN_C ACPI_STATUS AcpiOsReadPciConfiguration(ACPI_PCI_ID *address, UINT32 reg, UINT64 *value, UINT32 width) { | ||||||
|  | 	if (width == 64) { | ||||||
|  | 		uint64_t x = (uint64_t) KPCIReadConfig(address->Bus, address->Device, address->Function, reg) | ||||||
|  | 			| ((uint64_t) KPCIReadConfig(address->Bus, address->Device, address->Function, reg + 4) << 32); | ||||||
|  | 		*value = x; | ||||||
|  | 	} else { | ||||||
|  | 		uint32_t x = KPCIReadConfig(address->Bus, address->Device, address->Function, reg & ~3); | ||||||
|  | 		x >>= (reg & 3) * 8; | ||||||
|  | 
 | ||||||
|  | 		if (width == 8) x &= 0xFF; | ||||||
|  | 		if (width == 16) x &= 0xFFFF; | ||||||
|  | 
 | ||||||
|  | 		*value = x; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return AE_OK; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | ES_EXTERN_C ACPI_STATUS AcpiOsWritePciConfiguration(ACPI_PCI_ID *address, UINT32 reg, UINT64 value, UINT32 width) { | ||||||
|  | 	if (width == 64) { | ||||||
|  | 		KPCIWriteConfig(address->Bus, address->Device, address->Function, reg, value); | ||||||
|  | 		KPCIWriteConfig(address->Bus, address->Device, address->Function, reg + 4, value >> 32); | ||||||
|  | 	} else if (width == 32) { | ||||||
|  | 		KPCIWriteConfig(address->Bus, address->Device, address->Function, reg, value); | ||||||
|  | 	} else { | ||||||
|  | 		uint32_t x = KPCIReadConfig(address->Bus, address->Device, address->Function, reg & ~3); | ||||||
|  | 		uint32_t o = reg & 3; | ||||||
|  | 
 | ||||||
|  | 		if (width == 16) { | ||||||
|  | 			if (o == 2) { | ||||||
|  | 				x = (x & ~0xFFFF0000) | (value << 16); | ||||||
|  | 			} else { | ||||||
|  | 				x = (x & ~0x0000FFFF) | (value << 0); | ||||||
|  | 			} | ||||||
|  | 		} else if (width == 8) { | ||||||
|  | 			if (o == 3) { | ||||||
|  | 				x = (x & ~0xFF000000) | (value << 24); | ||||||
|  | 			} else if (o == 2) { | ||||||
|  | 				x = (x & ~0x00FF0000) | (value << 16); | ||||||
|  | 			} else if (o == 1) { | ||||||
|  | 				x = (x & ~0x0000FF00) | (value << 8); | ||||||
|  | 			} else { | ||||||
|  | 				x = (x & ~0x000000FF) | (value << 0); | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		KPCIWriteConfig(address->Bus, address->Device, address->Function, reg & ~3, x); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return AE_OK; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | ES_EXTERN_C void AcpiOsPrintf(const char *format, ...) { | ||||||
|  | 	va_list arguments; | ||||||
|  | 	va_start(arguments, format); | ||||||
|  | 	int x = stbsp_vsnprintf(acpiPrintf, sizeof(acpiPrintf), format, arguments); | ||||||
|  | 	EsPrint("%s", x, acpiPrintf); | ||||||
|  | 	va_end(arguments); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | ES_EXTERN_C void AcpiOsVprintf(const char *format, va_list arguments) { | ||||||
|  | 	int x = stbsp_vsnprintf(acpiPrintf, sizeof(acpiPrintf), format, arguments); | ||||||
|  | 	EsPrint("%s", x, acpiPrintf); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | ES_EXTERN_C UINT64 AcpiOsGetTimer() { | ||||||
|  | 	uint64_t tick = ProcessorReadTimeStamp(); | ||||||
|  | 	uint64_t ticksPerMs = timeStampTicksPerMs; | ||||||
|  | 	uint64_t ticksPer100Ns = ticksPerMs / 1000 / 10; | ||||||
|  | 	if (ticksPer100Ns == 0) return tick; | ||||||
|  | 	return tick / ticksPer100Ns; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | ES_EXTERN_C ACPI_STATUS AcpiOsSignal(UINT32 function, void *information) { | ||||||
|  | 	(void) function; | ||||||
|  | 	(void) information; | ||||||
|  | 	KernelPanic("AcpiOsSignal - ACPI requested kernel panic.\n"); | ||||||
|  | 	return AE_OK; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | ES_EXTERN_C ACPI_STATUS AcpiOsEnterSleep(UINT8 sleepState, UINT32 registerAValue, UINT32 registerBValue) { | ||||||
|  | 	(void) sleepState; | ||||||
|  | 	(void) registerAValue; | ||||||
|  | 	(void) registerBValue; | ||||||
|  | 	return AE_OK; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | UINT32 ACPIPowerButtonPressed(void *) { | ||||||
|  | 	KRegisterAsyncTask([] (EsGeneric) { | ||||||
|  | 		_EsMessageWithObject m = { nullptr, ES_MSG_POWER_BUTTON_PRESSED }; | ||||||
|  | 		if (scheduler.shutdown) return; | ||||||
|  | 		if (desktopProcess) desktopProcess->messageQueue.SendMessage(&m); | ||||||
|  | 	}, nullptr, false); | ||||||
|  | 
 | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | int32_t ACPIFindIRQ(ACPI_HANDLE object) { | ||||||
|  | 	ACPI_BUFFER buffer = {}; | ||||||
|  | 	ACPI_STATUS status = AcpiGetCurrentResources(object, &buffer); | ||||||
|  | 	if (status != AE_BUFFER_OVERFLOW) return -1; | ||||||
|  | 	buffer.Pointer = EsHeapAllocate(buffer.Length, false, K_FIXED); | ||||||
|  | 	EsDefer(EsHeapFree(buffer.Pointer, buffer.Length, K_FIXED)); | ||||||
|  | 	if (!buffer.Pointer) return -1; | ||||||
|  | 	status = AcpiGetCurrentResources(object, &buffer); | ||||||
|  | 	if (status != AE_OK) return -1; | ||||||
|  | 	ACPI_RESOURCE *resource = (ACPI_RESOURCE *) buffer.Pointer; | ||||||
|  | 
 | ||||||
|  | 	while (resource->Type != ACPI_RESOURCE_TYPE_END_TAG) { | ||||||
|  | 		if (resource->Type == ACPI_RESOURCE_TYPE_IRQ) { | ||||||
|  | 			if (resource->Data.Irq.InterruptCount) { | ||||||
|  | 				return resource->Data.Irq.Interrupts[0]; | ||||||
|  | 			} | ||||||
|  | 		} else if (resource->Type == ACPI_RESOURCE_TYPE_EXTENDED_IRQ) { | ||||||
|  | 			if (resource->Data.ExtendedIrq.InterruptCount) { | ||||||
|  | 				return resource->Data.ExtendedIrq.Interrupts[0]; | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		resource = (ACPI_RESOURCE *) ((uint8_t *) resource + resource->Length); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return -1; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void ACPIEnumeratePRTEntries(ACPI_HANDLE pciBus) { | ||||||
|  | 	// TODO Other PCI buses.
 | ||||||
|  | 	// TODO Is this always bus 0?
 | ||||||
|  | 
 | ||||||
|  | 	ACPI_BUFFER buffer = {}; | ||||||
|  | 	ACPI_STATUS status = AcpiGetIrqRoutingTable(pciBus, &buffer); | ||||||
|  | 	if (status != AE_BUFFER_OVERFLOW) return; | ||||||
|  | 	buffer.Pointer = EsHeapAllocate(buffer.Length, false, K_FIXED); | ||||||
|  | 	EsDefer(EsHeapFree(buffer.Pointer, buffer.Length, K_FIXED)); | ||||||
|  | 	if (!buffer.Pointer) return; | ||||||
|  | 	status = AcpiGetIrqRoutingTable(pciBus, &buffer); | ||||||
|  | 	if (status != AE_OK) return; | ||||||
|  | 	ACPI_PCI_ROUTING_TABLE *table = (ACPI_PCI_ROUTING_TABLE *) buffer.Pointer; | ||||||
|  | 
 | ||||||
|  | 	while (table->Length) { | ||||||
|  | 		ACPI_HANDLE source; | ||||||
|  | 
 | ||||||
|  | 		if (AE_OK == AcpiGetHandle(pciBus, table->Source, &source)) { | ||||||
|  | 			int32_t irq = ACPIFindIRQ(source); | ||||||
|  | 
 | ||||||
|  | 			if (irq != -1) { | ||||||
|  | 				KernelLog(LOG_INFO, "ACPI", "PRT entry", "Pin: %d; PCI slot: %X; IRQ: %d\n", | ||||||
|  | 						table->Pin, (table->Address >> 16) & 0xFF, irq); | ||||||
|  | 
 | ||||||
|  | 				if (irq != 9 && irq != 10 && irq != 11) { | ||||||
|  | 					KernelLog(LOG_ERROR, "ACPI", "unexpected IRQ", "IRQ %d was unexpected; expected values are 9, 10 or 11.\n", irq); | ||||||
|  | 				} else if ((table->Address >> 16) > 0xFF) { | ||||||
|  | 					KernelLog(LOG_ERROR, "ACPI", "unexpected address", "Address %x was larger than expected.\n", table->Address); | ||||||
|  | 				} else if (table->Pin > 3) { | ||||||
|  | 					KernelLog(LOG_ERROR, "ACPI", "unexpected pin", "Pin %d was larger than expected.\n", table->Pin); | ||||||
|  | 				} else { | ||||||
|  | 					ArchSetPCIIRQLine(table->Address >> 16, table->Pin, irq); | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		table = (ACPI_PCI_ROUTING_TABLE *) ((uint8_t *) table + table->Length); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | struct KACPIObject : KDevice { | ||||||
|  | 	ACPI_HANDLE handle; | ||||||
|  | 	KACPINotificationHandler notificationHandler; | ||||||
|  | 	EsGeneric notificationHandlerContext; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | void ACPINotificationHandler(ACPI_HANDLE, uint32_t value, void *context) { | ||||||
|  | 	KernelLog(LOG_INFO, "ACPI", "notification", "Received a notification with value %X.\n", value); | ||||||
|  | 	KACPIObject *object = (KACPIObject *) context; | ||||||
|  | 	object->notificationHandler(object, value, object->notificationHandlerContext); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | EsError KACPIObjectSetDeviceNotificationHandler(KACPIObject *object, KACPINotificationHandler handler, EsGeneric context) { | ||||||
|  | 	object->notificationHandler = handler; | ||||||
|  | 	object->notificationHandlerContext = context; | ||||||
|  | 	ACPI_STATUS status = AcpiInstallNotifyHandler(object->handle, ACPI_DEVICE_NOTIFY, ACPINotificationHandler, object); | ||||||
|  | 	if (status == AE_OK) return ES_SUCCESS; | ||||||
|  | 	else if (status == AE_NO_MEMORY) return ES_ERROR_INSUFFICIENT_RESOURCES; | ||||||
|  | 	else return ES_ERROR_UNKNOWN; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | EsError KACPIObjectEvaluateInteger(KACPIObject *object, const char *pathName, uint64_t *_integer) { | ||||||
|  | 	ACPI_BUFFER buffer = {}; | ||||||
|  | 	buffer.Length = ACPI_ALLOCATE_BUFFER; | ||||||
|  | 
 | ||||||
|  | 	ACPI_STATUS status = AcpiEvaluateObject(object->handle, (char *) pathName, nullptr, &buffer); | ||||||
|  | 	EsError error = ES_SUCCESS; | ||||||
|  | 
 | ||||||
|  | 	if (status == AE_OK) { | ||||||
|  | 		ACPI_OBJECT *result = (ACPI_OBJECT *) buffer.Pointer; | ||||||
|  | 
 | ||||||
|  | 		if (result->Type == ACPI_TYPE_INTEGER) { | ||||||
|  | 			if (_integer) { | ||||||
|  | 				*_integer = result->Integer.Value; | ||||||
|  | 			} | ||||||
|  | 		} else { | ||||||
|  | 			error = ES_ERROR_UNKNOWN; | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		ACPI_FREE(buffer.Pointer); | ||||||
|  | 	} else if (status == AE_NO_MEMORY) { | ||||||
|  | 		error = ES_ERROR_INSUFFICIENT_RESOURCES; | ||||||
|  | 	} else if (status == AE_NOT_FOUND) { | ||||||
|  | 		error = ES_ERROR_FILE_DOES_NOT_EXIST; | ||||||
|  | 	} else { | ||||||
|  | 		error = ES_ERROR_UNKNOWN; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return error; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | EsError KACPIObjectEvaluateMethodWithInteger(KACPIObject *object, const char *pathName, uint64_t integer) { | ||||||
|  | 	ACPI_OBJECT argument = {}; | ||||||
|  | 	argument.Type = ACPI_TYPE_INTEGER; | ||||||
|  | 	argument.Integer.Value = integer; | ||||||
|  | 	ACPI_OBJECT_LIST argumentList = {}; | ||||||
|  | 	argumentList.Count = 1; | ||||||
|  | 	argumentList.Pointer = &argument; | ||||||
|  | 	ACPI_STATUS status = AcpiEvaluateObject(object->handle, (char *) pathName, &argumentList, nullptr); | ||||||
|  | 	if (status == AE_OK) return ES_SUCCESS; | ||||||
|  | 	else if (status == AE_NO_MEMORY) return ES_ERROR_INSUFFICIENT_RESOURCES; | ||||||
|  | 	else if (status == AE_NOT_FOUND) return ES_ERROR_FILE_DOES_NOT_EXIST; | ||||||
|  | 	else return ES_ERROR_UNKNOWN; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | ACPI_STATUS ACPIWalkNamespaceCallback(ACPI_HANDLE object, uint32_t depth, void *, void **) { | ||||||
|  | 	ACPI_DEVICE_INFO *information; | ||||||
|  | 	AcpiGetObjectInfo(object, &information); | ||||||
|  | 
 | ||||||
|  | 	char name[5]; | ||||||
|  | 	EsMemoryCopy(name, &information->Name, 4); | ||||||
|  | 	name[4] = 0; | ||||||
|  | 
 | ||||||
|  | 	if (information->Type == ACPI_TYPE_DEVICE) { | ||||||
|  | 		KernelLog(LOG_INFO, "ACPI", "device object", "Found device object '%z' at depth %d with HID '%z', UID '%z' and address %x.\n", | ||||||
|  | 				name, depth, | ||||||
|  | 				(information->Valid & ACPI_VALID_HID) ? information->HardwareId.String : "??", | ||||||
|  | 				(information->Valid & ACPI_VALID_UID) ? information->UniqueId.String : "??", | ||||||
|  | 				(information->Valid & ACPI_VALID_ADR) ? information->Address : 0); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if (information->Type == ACPI_TYPE_THERMAL) { | ||||||
|  | 		KACPIObject *device = (KACPIObject *) KDeviceCreate("ACPI object", acpi.computer, sizeof(KACPIObject)); | ||||||
|  | 
 | ||||||
|  | 		if (device) { | ||||||
|  | 			device->handle = object; | ||||||
|  | 			KDeviceAttachByName(device, "ACPIThermal"); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	ACPI_FREE(information); | ||||||
|  | 	return AE_OK; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void ArchShutdown(uintptr_t action) { | ||||||
|  | 	if (action == SHUTDOWN_ACTION_RESTART) ProcessorReset(); | ||||||
|  | 	AcpiEnterSleepStatePrep(5); | ||||||
|  | 	ProcessorDisableInterrupts(); | ||||||
|  | 	AcpiEnterSleepState(5); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void ACPICAInitialise() { | ||||||
|  | 	AcpiInitializeSubsystem(); | ||||||
|  | 	AcpiInitializeTables(nullptr, 256, true); | ||||||
|  | 	AcpiLoadTables(); | ||||||
|  | 	AcpiEnableSubsystem(ACPI_FULL_INITIALIZATION); | ||||||
|  | 	AcpiInitializeObjects(ACPI_FULL_INITIALIZATION); | ||||||
|  | 
 | ||||||
|  | 	if (AE_OK == AcpiEnableEvent(ACPI_EVENT_POWER_BUTTON, 0) | ||||||
|  | 			&& AE_OK == AcpiInstallFixedEventHandler(ACPI_EVENT_POWER_BUTTON, ACPIPowerButtonPressed, nullptr)) { | ||||||
|  | 		KDeviceCreate("ACPI power button", acpi.computer, sizeof(KDevice)); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	void *result; | ||||||
|  | 	AcpiWalkNamespace(ACPI_TYPE_ANY, ACPI_ROOT_OBJECT, 10, ACPIWalkNamespaceCallback, nullptr, nullptr, &result); | ||||||
|  | 
 | ||||||
|  | 	ACPI_HANDLE pciBus; | ||||||
|  | 	char pciBusPath[] = "\\_SB_.PCI0"; | ||||||
|  | 
 | ||||||
|  | 	if (AE_OK == AcpiGetHandle(nullptr, pciBusPath, &pciBus)) { | ||||||
|  | 		ACPIEnumeratePRTEntries(pciBus); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | @ -1906,14 +1906,11 @@ void FSRegisterFileSystem(KFileSystem *fileSystem) { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void FSRegisterBlockDevice(KBlockDevice *device) { | void FSRegisterBlockDevice(KBlockDevice *device) { | ||||||
| #ifdef SERIAL_STARTUP |  | ||||||
| 	FSDetectFileSystem(device); |  | ||||||
| #else |  | ||||||
| 	KThreadCreate("FSDetect", [] (uintptr_t context) { | 	KThreadCreate("FSDetect", [] (uintptr_t context) { | ||||||
| 		FSDetectFileSystem((KBlockDevice *) context); | 		KBlockDevice *device = (KBlockDevice *) context; | ||||||
| 	}, (uintptr_t) device); | 		FSDetectFileSystem(device); | ||||||
| #endif |  | ||||||
| 		KDeviceSendConnectedMessage(device, ES_DEVICE_BLOCK); | 		KDeviceSendConnectedMessage(device, ES_DEVICE_BLOCK); | ||||||
|  | 	}, (uintptr_t) device); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void FSShutdown() { | void FSShutdown() { | ||||||
|  |  | ||||||
|  | @ -90,7 +90,7 @@ struct CPULocalStorage { | ||||||
| 	unsigned processorID; | 	unsigned processorID; | ||||||
| 	size_t spinlockCount; | 	size_t spinlockCount; | ||||||
| 
 | 
 | ||||||
| 	ArchCPU *archCPU; | 	struct ArchCPU *archCPU; | ||||||
| 
 | 
 | ||||||
| 	// TODO Have separate interrupt task threads and system worker threads (with no task limit).
 | 	// TODO Have separate interrupt task threads and system worker threads (with no task limit).
 | ||||||
| #define MAX_ASYNC_TASKS (256) | #define MAX_ASYNC_TASKS (256) | ||||||
|  | @ -121,54 +121,45 @@ extern "C" { | ||||||
| 	InterruptContext *ArchInitialiseThread(uintptr_t kernelStack, uintptr_t kernelStackSize, struct Thread *thread,  | 	InterruptContext *ArchInitialiseThread(uintptr_t kernelStack, uintptr_t kernelStackSize, struct Thread *thread,  | ||||||
| 			uintptr_t startAddress, uintptr_t argument1, uintptr_t argument2, | 			uintptr_t startAddress, uintptr_t argument1, uintptr_t argument2, | ||||||
| 			bool userland, uintptr_t stack, uintptr_t userStackSize); | 			bool userland, uintptr_t stack, uintptr_t userStackSize); | ||||||
| 	EsError ArchApplyRelocation(uintptr_t type, uint8_t *buffer, uintptr_t offset, uintptr_t result); |  | ||||||
| 	void ArchSwitchContext(struct InterruptContext *context, struct MMArchVAS *virtualAddressSpace, uintptr_t threadKernelStack,  | 	void ArchSwitchContext(struct InterruptContext *context, struct MMArchVAS *virtualAddressSpace, uintptr_t threadKernelStack,  | ||||||
| 			struct Thread *newThread, struct MMSpace *oldAddressSpace); | 			struct Thread *newThread, struct MMSpace *oldAddressSpace); | ||||||
|  | 	EsError ArchApplyRelocation(uintptr_t type, uint8_t *buffer, uintptr_t offset, uintptr_t result); | ||||||
| 
 | 
 | ||||||
| 	void MMArchRemap(MMSpace *space, const void *virtualAddress, uintptr_t newPhysicalAddress); // Must be done with interrupts disabled; does not invalidate on other processors.
 |  | ||||||
| 	bool MMArchMapPage(MMSpace *space, uintptr_t physicalAddress, uintptr_t virtualAddress, unsigned flags); // Returns false if the page was already mapped.
 | 	bool MMArchMapPage(MMSpace *space, uintptr_t physicalAddress, uintptr_t virtualAddress, unsigned flags); // Returns false if the page was already mapped.
 | ||||||
| 	void MMArchUnmapPages(MMSpace *space, uintptr_t virtualAddressStart, uintptr_t pageCount, unsigned flags, size_t unmapMaximum = 0, uintptr_t *resumePosition = nullptr); | 	void MMArchUnmapPages(MMSpace *space, uintptr_t virtualAddressStart, uintptr_t pageCount, unsigned flags, size_t unmapMaximum = 0, uintptr_t *resumePosition = nullptr); | ||||||
| 	void MMArchInvalidatePages(uintptr_t virtualAddressStart, uintptr_t pageCount); | 	void MMArchRemap(MMSpace *space, const void *virtualAddress, uintptr_t newPhysicalAddress); // Must be done with interrupts disabled; does not invalidate on other processors.
 | ||||||
| 	bool MMArchHandlePageFault(uintptr_t address, uint32_t flags); |  | ||||||
| 	void MMArchInitialiseVAS(); |  | ||||||
| 	bool MMArchInitialiseUserSpace(MMSpace *space); |  | ||||||
| 	bool MMArchCommitPageTables(MMSpace *space, struct MMRegion *region); |  | ||||||
| 	bool MMArchMakePageWritable(MMSpace *space, uintptr_t virtualAddress); | 	bool MMArchMakePageWritable(MMSpace *space, uintptr_t virtualAddress); | ||||||
|  | 	bool MMArchHandlePageFault(uintptr_t address, uint32_t flags); | ||||||
|  | 	void MMArchInvalidatePages(uintptr_t virtualAddressStart, uintptr_t pageCount); | ||||||
| 	bool MMArchIsBufferInUserRange(uintptr_t baseAddress, size_t byteCount); | 	bool MMArchIsBufferInUserRange(uintptr_t baseAddress, size_t byteCount); | ||||||
| 	bool MMArchSafeCopy(uintptr_t destinationAddress, uintptr_t sourceAddress, size_t byteCount); // Returns false if a page fault occured during the copy.
 | 	bool MMArchSafeCopy(uintptr_t destinationAddress, uintptr_t sourceAddress, size_t byteCount); // Returns false if a page fault occured during the copy.
 | ||||||
|  | 	bool MMArchCommitPageTables(MMSpace *space, struct MMRegion *region); | ||||||
|  | 	bool MMArchInitialiseUserSpace(MMSpace *space, struct MMRegion *firstRegion); | ||||||
|  | 	void MMArchInitialise(); | ||||||
| 	void MMArchFreeVAS(MMSpace *space); | 	void MMArchFreeVAS(MMSpace *space); | ||||||
| 	void MMArchFinalizeVAS(MMSpace *space); | 	void MMArchFinalizeVAS(MMSpace *space); | ||||||
|  | 	uintptr_t MMArchEarlyAllocatePage(); | ||||||
|  | 	uint64_t MMArchPopulatePageFrameDatabase(); | ||||||
|  | 	uintptr_t MMArchGetPhysicalMemoryHighest(); | ||||||
| 
 | 
 | ||||||
| 	void ProcessorDisableInterrupts(); | 	void ProcessorDisableInterrupts(); | ||||||
| 	void ProcessorEnableInterrupts(); | 	void ProcessorEnableInterrupts(); | ||||||
| 	bool ProcessorAreInterruptsEnabled(); | 	bool ProcessorAreInterruptsEnabled(); | ||||||
| 
 |  | ||||||
| 	void ArchResetCPU(); |  | ||||||
| 	void ProcessorHalt(); | 	void ProcessorHalt(); | ||||||
| 	void ProcessorSendYieldIPI(Thread *thread); | 	void ProcessorSendYieldIPI(Thread *thread); | ||||||
| 	void ProcessorFakeTimerInterrupt(); | 	void ProcessorFakeTimerInterrupt(); | ||||||
| 
 |  | ||||||
| 	void ProcessorInvalidatePage(uintptr_t virtualAddress); | 	void ProcessorInvalidatePage(uintptr_t virtualAddress); | ||||||
| 	void ProcessorInvalidateAllPages(); | 	void ProcessorInvalidateAllPages(); | ||||||
| 	void ProcessorFlushCodeCache(); | 	void ProcessorFlushCodeCache(); | ||||||
| 	void ProcessorFlushCache(); | 	void ProcessorFlushCache(); | ||||||
| 
 |  | ||||||
| 	void ProcessorSetLocalStorage(struct CPULocalStorage *cls); | 	void ProcessorSetLocalStorage(struct CPULocalStorage *cls); | ||||||
| 	void ProcessorSetThreadStorage(uintptr_t tls); | 	void ProcessorSetThreadStorage(uintptr_t tls); | ||||||
| 	void ProcessorSetAddressSpace(struct MMArchVAS *virtualAddressSpace); // Need to call MMSpaceOpenReference/MMSpaceCloseReference if using this.
 | 	void ProcessorSetAddressSpace(struct MMArchVAS *virtualAddressSpace); // Need to call MMSpaceOpenReference/MMSpaceCloseReference if using this.
 | ||||||
| 
 |  | ||||||
| 	uint64_t ProcessorReadTimeStamp(); | 	uint64_t ProcessorReadTimeStamp(); | ||||||
| 
 | 
 | ||||||
| 	struct CPULocalStorage *GetLocalStorage(); | 	struct CPULocalStorage *GetLocalStorage(); | ||||||
| 	struct Thread *GetCurrentThread(); | 	struct Thread *GetCurrentThread(); | ||||||
| 
 | 
 | ||||||
| 	extern PhysicalMemoryRegion *physicalMemoryRegions; |  | ||||||
| 	extern size_t physicalMemoryRegionsCount; |  | ||||||
| 	extern size_t physicalMemoryRegionsPagesCount; |  | ||||||
| 	extern size_t physicalMemoryOriginalPagesCount; |  | ||||||
| 	extern size_t physicalMemoryRegionsIndex; |  | ||||||
| 	extern uintptr_t physicalMemoryHighest; |  | ||||||
| 
 |  | ||||||
| 	// From module.h: 
 | 	// From module.h: 
 | ||||||
| 	// uintptr_t MMArchTranslateAddress(MMSpace *space, uintptr_t virtualAddress, bool writeAccess); 
 | 	// uintptr_t MMArchTranslateAddress(MMSpace *space, uintptr_t virtualAddress, bool writeAccess); 
 | ||||||
| 	// uint32_t KPCIReadConfig(uint8_t bus, uint8_t device, uint8_t function, uint8_t offset, int size);
 | 	// uint32_t KPCIReadConfig(uint8_t bus, uint8_t device, uint8_t function, uint8_t offset, int size);
 | ||||||
|  | @ -176,6 +167,16 @@ extern "C" { | ||||||
| 	// bool KRegisterIRQ(intptr_t interruptIndex, KIRQHandler handler, void *context, const char *cOwnerName, struct KPCIDevice *pciDevice);
 | 	// bool KRegisterIRQ(intptr_t interruptIndex, KIRQHandler handler, void *context, const char *cOwnerName, struct KPCIDevice *pciDevice);
 | ||||||
| 	// KMSIInformation KRegisterMSI(KIRQHandler handler, void *context, const char *cOwnerName);
 | 	// KMSIInformation KRegisterMSI(KIRQHandler handler, void *context, const char *cOwnerName);
 | ||||||
| 	// void KUnregisterMSI(uintptr_t tag);
 | 	// void KUnregisterMSI(uintptr_t tag);
 | ||||||
|  | 	// size_t KGetCPUCount();
 | ||||||
|  | 	// struct CPULocalStorage *KGetCPULocal(uintptr_t index);
 | ||||||
|  | 
 | ||||||
|  | 	// The architecture layer must also define:
 | ||||||
|  | 	// - MM_CORE_REGIONS_START and MM_CORE_REGIONS_COUNT.
 | ||||||
|  | 	// - MM_KERNEL_SPACE_START and MM_KERNEL_SPACE_SIZE.
 | ||||||
|  | 	// - MM_MODULES_START and MM_MODULES_SIZE.
 | ||||||
|  | 	// - ArchCheckBundleHeader, ArchCheckELFHeader and ArchIsAddressInKernelSpace.
 | ||||||
|  | 	// - K_ARCH_STACK_GROWS_DOWN or K_ARCH_STACK_GROWS_UP.
 | ||||||
|  | 	// - K_ARCH_NAME.
 | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| #endif | #endif | ||||||
|  | @ -253,7 +254,7 @@ void EsAssertionFailure(const char *file, int line) { | ||||||
| 
 | 
 | ||||||
| #if defined(ARCH_X86_64) && defined(IMPLEMENTATION) | #if defined(ARCH_X86_64) && defined(IMPLEMENTATION) | ||||||
| #include "x86_64.h" | #include "x86_64.h" | ||||||
| #include "terminal.cpp" |  | ||||||
| #include <drivers/acpi.cpp> | #include <drivers/acpi.cpp> | ||||||
| #include "x86_64.cpp" | #include "x86_64.cpp" | ||||||
|  | #include "terminal.cpp" | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
|  | @ -153,6 +153,8 @@ struct Pool { | ||||||
| 
 | 
 | ||||||
| struct PMM { | struct PMM { | ||||||
| 	MMPageFrame *pageFrames; | 	MMPageFrame *pageFrames; | ||||||
|  | 	bool pageFrameDatabaseInitialised; | ||||||
|  | 	uintptr_t pageFrameDatabaseCount; | ||||||
| 
 | 
 | ||||||
| 	uintptr_t firstFreePage; | 	uintptr_t firstFreePage; | ||||||
| 	uintptr_t firstZeroedPage; | 	uintptr_t firstZeroedPage; | ||||||
|  | @ -426,39 +428,23 @@ uintptr_t MMPhysicalAllocate(unsigned flags, uintptr_t count, uintptr_t align, u | ||||||
| 
 | 
 | ||||||
| 	bool simple = count == 1 && align == 1 && below == 0; | 	bool simple = count == 1 && align == 1 && below == 0; | ||||||
| 
 | 
 | ||||||
| 	if (physicalMemoryRegionsPagesCount) { | 	if (!pmm.pageFrameDatabaseInitialised) { | ||||||
| 		// Early page allocation before the page frame database is initialised.
 | 		// Early page allocation before the page frame database is initialised.
 | ||||||
| 
 | 
 | ||||||
| 		if (!simple) { | 		if (!simple) { | ||||||
| 			KernelPanic("MMPhysicalAllocate - Non-simple allocation before initialisation of the page frame database.\n"); | 			KernelPanic("MMPhysicalAllocate - Non-simple allocation before initialisation of the page frame database.\n"); | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		uintptr_t i = physicalMemoryRegionsIndex; | 		uintptr_t page = MMArchEarlyAllocatePage(); | ||||||
| 
 |  | ||||||
| 		while (!physicalMemoryRegions[i].pageCount) { |  | ||||||
| 			i++; |  | ||||||
| 
 |  | ||||||
| 			if (i == physicalMemoryRegionsCount) { |  | ||||||
| 				KernelPanic("MMPhysicalAllocate - Expected more pages in physical regions.\n"); |  | ||||||
| 			} |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		PhysicalMemoryRegion *region = physicalMemoryRegions + i; |  | ||||||
| 		uintptr_t returnValue = region->baseAddress; |  | ||||||
| 
 |  | ||||||
| 		region->baseAddress += K_PAGE_SIZE; |  | ||||||
| 		region->pageCount--; |  | ||||||
| 		physicalMemoryRegionsPagesCount--; |  | ||||||
| 		physicalMemoryRegionsIndex = i; |  | ||||||
| 
 | 
 | ||||||
| 		if (flags & MM_PHYSICAL_ALLOCATE_ZEROED) { | 		if (flags & MM_PHYSICAL_ALLOCATE_ZEROED) { | ||||||
| 			// TODO Hack!
 | 			// TODO Hack!
 | ||||||
| 			MMArchMapPage(coreMMSpace, returnValue, (uintptr_t) earlyZeroBuffer,  | 			MMArchMapPage(coreMMSpace, page, (uintptr_t) earlyZeroBuffer,  | ||||||
| 					MM_MAP_PAGE_OVERWRITE | MM_MAP_PAGE_NO_NEW_TABLES | MM_MAP_PAGE_FRAME_LOCK_ACQUIRED); | 					MM_MAP_PAGE_OVERWRITE | MM_MAP_PAGE_NO_NEW_TABLES | MM_MAP_PAGE_FRAME_LOCK_ACQUIRED); | ||||||
| 			EsMemoryZero(earlyZeroBuffer, K_PAGE_SIZE); | 			EsMemoryZero(earlyZeroBuffer, K_PAGE_SIZE); | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		return returnValue; | 		return page; | ||||||
| 	} else if (!simple) { | 	} else if (!simple) { | ||||||
| 		// Slow path.
 | 		// Slow path.
 | ||||||
| 		// TODO Use standby pages.
 | 		// TODO Use standby pages.
 | ||||||
|  | @ -524,7 +510,7 @@ void MMPhysicalFree(uintptr_t page, bool mutexAlreadyAcquired, size_t count) { | ||||||
| 	if (!page) KernelPanic("MMPhysicalFree - Invalid page.\n"); | 	if (!page) KernelPanic("MMPhysicalFree - Invalid page.\n"); | ||||||
| 	if (mutexAlreadyAcquired) KMutexAssertLocked(&pmm.pageFrameMutex); | 	if (mutexAlreadyAcquired) KMutexAssertLocked(&pmm.pageFrameMutex); | ||||||
| 	else KMutexAcquire(&pmm.pageFrameMutex); | 	else KMutexAcquire(&pmm.pageFrameMutex); | ||||||
| 	if (physicalMemoryRegionsPagesCount) KernelPanic("MMPhysicalFree - PMM not yet initialised.\n"); | 	if (!pmm.pageFrameDatabaseInitialised) KernelPanic("MMPhysicalFree - PMM not yet initialised.\n"); | ||||||
| 
 | 
 | ||||||
| 	page >>= K_PAGE_BITS; | 	page >>= K_PAGE_BITS; | ||||||
| 
 | 
 | ||||||
|  | @ -551,7 +537,7 @@ void MMPhysicalFree(uintptr_t page, bool mutexAlreadyAcquired, size_t count) { | ||||||
| 
 | 
 | ||||||
| void MMCheckUnusable(uintptr_t physicalStart, size_t bytes) { | void MMCheckUnusable(uintptr_t physicalStart, size_t bytes) { | ||||||
| 	for (uintptr_t i = physicalStart / K_PAGE_SIZE; i < (physicalStart + bytes + K_PAGE_SIZE - 1) / K_PAGE_SIZE | 	for (uintptr_t i = physicalStart / K_PAGE_SIZE; i < (physicalStart + bytes + K_PAGE_SIZE - 1) / K_PAGE_SIZE | ||||||
| 			&& i < physicalMemoryHighest / K_PAGE_SIZE; i++) { | 			&& i < pmm.pageFrameDatabaseCount; i++) { | ||||||
| 		if (pmm.pageFrames[i].state != MMPageFrame::UNUSABLE) { | 		if (pmm.pageFrames[i].state != MMPageFrame::UNUSABLE) { | ||||||
| 			KernelPanic("MMCheckUnusable - Page frame at address %x should be unusable.\n", i * K_PAGE_SIZE); | 			KernelPanic("MMCheckUnusable - Page frame at address %x should be unusable.\n", i * K_PAGE_SIZE); | ||||||
| 		} | 		} | ||||||
|  | @ -1587,13 +1573,11 @@ bool MMSpaceInitialise(MMSpace *space) { | ||||||
| 		return false; | 		return false; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	if (!MMArchInitialiseUserSpace(space)) { | 	if (!MMArchInitialiseUserSpace(space, region)) { | ||||||
| 		EsHeapFree(region, sizeof(MMRegion), K_CORE); | 		EsHeapFree(region, sizeof(MMRegion), K_CORE); | ||||||
| 		return false; | 		return false; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	region->baseAddress = MM_USER_SPACE_START;  |  | ||||||
| 	region->pageCount = MM_USER_SPACE_SIZE / K_PAGE_SIZE; |  | ||||||
| 	TreeInsert(&space->freeRegionsBase, ®ion->itemBase, region, MakeShortKey(region->baseAddress)); | 	TreeInsert(&space->freeRegionsBase, ®ion->itemBase, region, MakeShortKey(region->baseAddress)); | ||||||
| 	TreeInsert(&space->freeRegionsSize, ®ion->itemSize, region, MakeShortKey(region->pageCount), AVL_DUPLICATE_KEYS_ALLOW); | 	TreeInsert(&space->freeRegionsSize, ®ion->itemSize, region, MakeShortKey(region->pageCount), AVL_DUPLICATE_KEYS_ALLOW); | ||||||
| 
 | 
 | ||||||
|  | @ -2276,21 +2260,11 @@ void MMSpaceCloseReference(MMSpace *space) { | ||||||
| 
 | 
 | ||||||
| void MMInitialise() { | void MMInitialise() { | ||||||
| 	{ | 	{ | ||||||
| 		// Initialise coreMMSpace.
 | 		// Initialise coreMMSpace and kernelMMSpace.
 | ||||||
| 
 | 
 | ||||||
| 		MMArchInitialiseVAS(); |  | ||||||
| 		mmCoreRegions[0].baseAddress = MM_CORE_SPACE_START; |  | ||||||
| 		mmCoreRegions[0].pageCount = MM_CORE_SPACE_SIZE / K_PAGE_SIZE; |  | ||||||
| 		mmCoreRegions[0].core.used = false; | 		mmCoreRegions[0].core.used = false; | ||||||
| 		mmCoreRegionCount = 1; | 		mmCoreRegionCount = 1; | ||||||
| 	} | 		MMArchInitialise(); | ||||||
| 
 |  | ||||||
| 	{ |  | ||||||
| 		// Initialise kernelMMSpace.
 |  | ||||||
| 
 |  | ||||||
| 		KMutexAcquire(&coreMMSpace->reserveMutex); |  | ||||||
| 		kernelMMSpace->data.l1Commit = (uint8_t *) MMReserve(coreMMSpace, L1_COMMIT_SIZE_BYTES, MM_REGION_NORMAL | MM_REGION_NO_COMMIT_TRACKING | MM_REGION_FIXED)->baseAddress; |  | ||||||
| 		KMutexRelease(&coreMMSpace->reserveMutex); |  | ||||||
| 
 | 
 | ||||||
| 		MMRegion *region = (MMRegion *) EsHeapAllocate(sizeof(MMRegion), true, K_CORE); | 		MMRegion *region = (MMRegion *) EsHeapAllocate(sizeof(MMRegion), true, K_CORE); | ||||||
| 		region->baseAddress = MM_KERNEL_SPACE_START;  | 		region->baseAddress = MM_KERNEL_SPACE_START;  | ||||||
|  | @ -2306,25 +2280,16 @@ void MMInitialise() { | ||||||
| 		pmm.pmManipulationRegion = (void *) MMReserve(kernelMMSpace, PHYSICAL_MEMORY_MANIPULATION_REGION_PAGES * K_PAGE_SIZE, ES_FLAGS_DEFAULT)->baseAddress;  | 		pmm.pmManipulationRegion = (void *) MMReserve(kernelMMSpace, PHYSICAL_MEMORY_MANIPULATION_REGION_PAGES * K_PAGE_SIZE, ES_FLAGS_DEFAULT)->baseAddress;  | ||||||
| 		KMutexRelease(&kernelMMSpace->reserveMutex); | 		KMutexRelease(&kernelMMSpace->reserveMutex); | ||||||
| 
 | 
 | ||||||
| 		physicalMemoryHighest += K_PAGE_SIZE << 3; // 1 extra for the top page, then round up so the page bitset is byte-aligned.
 | 		// 1 extra for the top page, then round up so the page bitset is byte-aligned.
 | ||||||
| 		pmm.pageFrames = (MMPageFrame *) MMStandardAllocate(kernelMMSpace, (physicalMemoryHighest >> K_PAGE_BITS) * sizeof(MMPageFrame), MM_REGION_FIXED); | 		pmm.pageFrameDatabaseCount = (MMArchGetPhysicalMemoryHighest() + (K_PAGE_SIZE << 3)) >> K_PAGE_BITS;  | ||||||
| 		pmm.freeOrZeroedPageBitset.Initialise(physicalMemoryHighest >> K_PAGE_BITS, true); | 
 | ||||||
|  | 		pmm.pageFrames = (MMPageFrame *) MMStandardAllocate(kernelMMSpace, pmm.pageFrameDatabaseCount * sizeof(MMPageFrame), MM_REGION_FIXED); | ||||||
|  | 		pmm.freeOrZeroedPageBitset.Initialise(pmm.pageFrameDatabaseCount, true); | ||||||
| 
 | 
 | ||||||
| 		uint64_t commitLimit = 0; |  | ||||||
| 		MMPhysicalInsertFreePagesStart(); | 		MMPhysicalInsertFreePagesStart(); | ||||||
| 
 | 		uint64_t commitLimit = MMArchPopulatePageFrameDatabase(); | ||||||
| 		for (uintptr_t i = 0; i < physicalMemoryRegionsCount; i++) { |  | ||||||
| 			uintptr_t base = physicalMemoryRegions[i].baseAddress >> K_PAGE_BITS; |  | ||||||
| 			uintptr_t count = physicalMemoryRegions[i].pageCount; |  | ||||||
| 			commitLimit += count; |  | ||||||
| 
 |  | ||||||
| 			for (uintptr_t j = 0; j < count; j++) { |  | ||||||
| 				MMPhysicalInsertFreePagesNext(base + j); |  | ||||||
| 			} |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		MMPhysicalInsertFreePagesEnd(); | 		MMPhysicalInsertFreePagesEnd(); | ||||||
| 		physicalMemoryRegionsPagesCount = 0; | 		pmm.pageFrameDatabaseInitialised = true; | ||||||
| 
 | 
 | ||||||
| 		pmm.commitLimit = pmm.commitFixedLimit = commitLimit; | 		pmm.commitLimit = pmm.commitFixedLimit = commitLimit; | ||||||
| 		KernelLog(LOG_INFO, "Memory", "pmm initialised", "MMInitialise - PMM initialised with a fixed commit limit of %d pages.\n", pmm.commitLimit); | 		KernelLog(LOG_INFO, "Memory", "pmm initialised", "MMInitialise - PMM initialised with a fixed commit limit of %d pages.\n", pmm.commitLimit); | ||||||
|  | @ -2337,7 +2302,7 @@ void MMInitialise() { | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	{ | 	{ | ||||||
| 		// Thread initialisation.
 | 		// Create threads.
 | ||||||
| 
 | 
 | ||||||
| 		pmm.zeroPageEvent.autoReset = true; | 		pmm.zeroPageEvent.autoReset = true; | ||||||
| 		MMCommit(PHYSICAL_MEMORY_MANIPULATION_REGION_PAGES * K_PAGE_SIZE, true); | 		MMCommit(PHYSICAL_MEMORY_MANIPULATION_REGION_PAGES * K_PAGE_SIZE, true); | ||||||
|  |  | ||||||
|  | @ -1859,7 +1859,6 @@ SYSCALL_IMPLEMENT(ES_SYSCALL_DEBUG_COMMAND) { | ||||||
| 
 | 
 | ||||||
| #ifdef DEBUG_BUILD | #ifdef DEBUG_BUILD | ||||||
| 	if (argument0 == 1) { | 	if (argument0 == 1) { | ||||||
| 		ArchResetCPU(); |  | ||||||
| 	} else if (argument0 == 2) { | 	} else if (argument0 == 2) { | ||||||
| 		KernelPanic("Debug command 2.\n"); | 		KernelPanic("Debug command 2.\n"); | ||||||
| 	} else if (argument0 == 4) { | 	} else if (argument0 == 4) { | ||||||
|  |  | ||||||
|  | @ -356,7 +356,7 @@ void KernelPanic(const char *format, ...) { | ||||||
| 
 | 
 | ||||||
| 			KWaitKey(); | 			KWaitKey(); | ||||||
| 		} else if (key == ES_SCANCODE_1) { | 		} else if (key == ES_SCANCODE_1) { | ||||||
| 			ArchResetCPU(); | 			ProcessorReset(); | ||||||
| 		} else if (key == ES_SCANCODE_2) { | 		} else if (key == ES_SCANCODE_2) { | ||||||
| 			EsPrint("Enter address: "); | 			EsPrint("Enter address: "); | ||||||
| 			uintptr_t address = DebugReadNumber(); | 			uintptr_t address = DebugReadNumber(); | ||||||
|  |  | ||||||
|  | @ -1,17 +1,5 @@ | ||||||
| #ifndef IMPLEMENTATION | #ifndef IMPLEMENTATION | ||||||
| 
 | 
 | ||||||
| typedef struct ACPIProcessor ArchCPU; |  | ||||||
| 
 |  | ||||||
| struct InterruptContext { |  | ||||||
| 	uint64_t cr2, ds; |  | ||||||
| 	uint8_t  fxsave[512 + 16]; |  | ||||||
| 	uint64_t _check, cr8; |  | ||||||
| 	uint64_t r15, r14, r13, r12, r11, r10, r9, r8; |  | ||||||
| 	uint64_t rbp, rdi, rsi, rdx, rcx, rbx, rax; |  | ||||||
| 	uint64_t interruptNumber, errorCode; |  | ||||||
| 	uint64_t rip, cs, flags, rsp, ss; |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| struct MMArchVAS { | struct MMArchVAS { | ||||||
| 	// NOTE Must be first in the structure. See ProcessorSetAddressSpace and ArchSwitchContext.
 | 	// NOTE Must be first in the structure. See ProcessorSetAddressSpace and ArchSwitchContext.
 | ||||||
| 	uintptr_t cr3; | 	uintptr_t cr3; | ||||||
|  | @ -40,16 +28,12 @@ struct MMArchVAS { | ||||||
| 	KMutex mutex; // Acquire to modify the page tables.
 | 	KMutex mutex; // Acquire to modify the page tables.
 | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| #define MM_CORE_SPACE_START   (0xFFFF800100000000) |  | ||||||
| #define MM_CORE_SPACE_SIZE    (0xFFFF8001F0000000 - 0xFFFF800100000000) |  | ||||||
| #define MM_CORE_REGIONS_START (0xFFFF8001F0000000) | #define MM_CORE_REGIONS_START (0xFFFF8001F0000000) | ||||||
| #define MM_CORE_REGIONS_COUNT ((0xFFFF800200000000 - 0xFFFF8001F0000000) / sizeof(MMRegion)) | #define MM_CORE_REGIONS_COUNT ((0xFFFF800200000000 - 0xFFFF8001F0000000) / sizeof(MMRegion)) | ||||||
| #define MM_KERNEL_SPACE_START (0xFFFF900000000000) | #define MM_KERNEL_SPACE_START (0xFFFF900000000000) | ||||||
| #define MM_KERNEL_SPACE_SIZE  (0xFFFFF00000000000 - 0xFFFF900000000000) | #define MM_KERNEL_SPACE_SIZE  (0xFFFFF00000000000 - 0xFFFF900000000000) | ||||||
| #define MM_MODULES_START      (0xFFFFFFFF90000000) | #define MM_MODULES_START      (0xFFFFFFFF90000000) | ||||||
| #define MM_MODULES_SIZE	      (0xFFFFFFFFC0000000 - 0xFFFFFFFF90000000) | #define MM_MODULES_SIZE	      (0xFFFFFFFFC0000000 - 0xFFFFFFFF90000000) | ||||||
| #define MM_USER_SPACE_START   (0x100000000000) |  | ||||||
| #define MM_USER_SPACE_SIZE    (0xF00000000000 - 0x100000000000) |  | ||||||
| 
 | 
 | ||||||
| #define ArchCheckBundleHeader()       (header.mapAddress > 0x800000000000UL || header.mapAddress < 0x1000 || fileSize > 0x1000000000000UL) | #define ArchCheckBundleHeader()       (header.mapAddress > 0x800000000000UL || header.mapAddress < 0x1000 || fileSize > 0x1000000000000UL) | ||||||
| #define ArchCheckELFHeader()          (header->virtualAddress > 0x800000000000UL || header->virtualAddress < 0x1000 || header->segmentSize > 0x1000000000000UL) | #define ArchCheckELFHeader()          (header->virtualAddress > 0x800000000000UL || header->virtualAddress < 0x1000 || header->segmentSize > 0x1000000000000UL) | ||||||
|  | @ -62,6 +46,11 @@ struct MMArchVAS { | ||||||
| 
 | 
 | ||||||
| #ifdef IMPLEMENTATION | #ifdef IMPLEMENTATION | ||||||
| 
 | 
 | ||||||
|  | #define MM_CORE_SPACE_START   (0xFFFF800100000000) | ||||||
|  | #define MM_CORE_SPACE_SIZE    (0xFFFF8001F0000000 - 0xFFFF800100000000) | ||||||
|  | #define MM_USER_SPACE_START   (0x100000000000) | ||||||
|  | #define MM_USER_SPACE_SIZE    (0xF00000000000 - 0x100000000000) | ||||||
|  | 
 | ||||||
| struct MSIHandler { | struct MSIHandler { | ||||||
| 	KIRQHandler callback; | 	KIRQHandler callback; | ||||||
| 	void *context; | 	void *context; | ||||||
|  | @ -75,6 +64,13 @@ struct IRQHandler { | ||||||
| 	const char *cOwnerName; | 	const char *cOwnerName; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  | extern PhysicalMemoryRegion *physicalMemoryRegions; | ||||||
|  | extern size_t physicalMemoryRegionsCount; | ||||||
|  | extern size_t physicalMemoryRegionsPagesCount; | ||||||
|  | extern size_t physicalMemoryOriginalPagesCount; | ||||||
|  | extern size_t physicalMemoryRegionsIndex; | ||||||
|  | extern uintptr_t physicalMemoryHighest; | ||||||
|  | 
 | ||||||
| uint8_t pciIRQLines[0x100 /* slots */][4 /* pins */]; | uint8_t pciIRQLines[0x100 /* slots */][4 /* pins */]; | ||||||
| 
 | 
 | ||||||
| MSIHandler msiHandlers[INTERRUPT_VECTOR_MSI_COUNT]; | MSIHandler msiHandlers[INTERRUPT_VECTOR_MSI_COUNT]; | ||||||
|  | @ -194,7 +190,7 @@ bool MMArchMapPage(MMSpace *space, uintptr_t physicalAddress, uintptr_t virtualA | ||||||
| 		KernelPanic("MMArchMapPage - Physical address not page aligned.\n"); | 		KernelPanic("MMArchMapPage - Physical address not page aligned.\n"); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	if (pmm.pageFrames && physicalAddress < physicalMemoryHighest) { | 	if (pmm.pageFrames && (physicalAddress >> K_PAGE_BITS) < pmm.pageFrameDatabaseCount) { | ||||||
| 		if (pmm.pageFrames[physicalAddress >> K_PAGE_BITS].state != MMPageFrame::ACTIVE | 		if (pmm.pageFrames[physicalAddress >> K_PAGE_BITS].state != MMPageFrame::ACTIVE | ||||||
| 				&& pmm.pageFrames[physicalAddress >> K_PAGE_BITS].state != MMPageFrame::UNUSABLE) { | 				&& pmm.pageFrames[physicalAddress >> K_PAGE_BITS].state != MMPageFrame::UNUSABLE) { | ||||||
| 			KernelPanic("MMArchMapPage - Physical page frame %x not marked as ACTIVE or UNUSABLE.\n", physicalAddress); | 			KernelPanic("MMArchMapPage - Physical page frame %x not marked as ACTIVE or UNUSABLE.\n", physicalAddress); | ||||||
|  | @ -361,10 +357,13 @@ bool MMArchHandlePageFault(uintptr_t address, uint32_t flags) { | ||||||
| 	return false; | 	return false; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void MMArchInitialiseVAS() { | void MMArchInitialise() { | ||||||
| 	coreMMSpace->data.cr3 = kernelMMSpace->data.cr3 = ProcessorReadCR3(); | 	coreMMSpace->data.cr3 = kernelMMSpace->data.cr3 = ProcessorReadCR3(); | ||||||
| 	coreMMSpace->data.l1Commit = coreL1Commit; | 	coreMMSpace->data.l1Commit = coreL1Commit; | ||||||
| 
 | 
 | ||||||
|  | 	mmCoreRegions[0].baseAddress = MM_CORE_SPACE_START; | ||||||
|  | 	mmCoreRegions[0].pageCount = MM_CORE_SPACE_SIZE / K_PAGE_SIZE; | ||||||
|  | 
 | ||||||
| 	for (uintptr_t i = 0x100; i < 0x200; i++) { | 	for (uintptr_t i = 0x100; i < 0x200; i++) { | ||||||
| 		if (PAGE_TABLE_L4[i] == 0) { | 		if (PAGE_TABLE_L4[i] == 0) { | ||||||
| 			// We don't need to commit anything because the PMM isn't ready yet.
 | 			// We don't need to commit anything because the PMM isn't ready yet.
 | ||||||
|  | @ -372,6 +371,10 @@ void MMArchInitialiseVAS() { | ||||||
| 			EsMemoryZero((void *) (PAGE_TABLE_L3 + i * 0x200), K_PAGE_SIZE); | 			EsMemoryZero((void *) (PAGE_TABLE_L3 + i * 0x200), K_PAGE_SIZE); | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  | 
 | ||||||
|  | 	KMutexAcquire(&coreMMSpace->reserveMutex); | ||||||
|  | 	kernelMMSpace->data.l1Commit = (uint8_t *) MMReserve(coreMMSpace, L1_COMMIT_SIZE_BYTES, MM_REGION_NORMAL | MM_REGION_NO_COMMIT_TRACKING | MM_REGION_FIXED)->baseAddress; | ||||||
|  | 	KMutexRelease(&coreMMSpace->reserveMutex); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| uintptr_t MMArchTranslateAddress(MMSpace *, uintptr_t virtualAddress, bool writeAccess) { | uintptr_t MMArchTranslateAddress(MMSpace *, uintptr_t virtualAddress, bool writeAccess) { | ||||||
|  | @ -549,7 +552,10 @@ InterruptContext *ArchInitialiseThread(uintptr_t kernelStack, uintptr_t kernelSt | ||||||
| 	return context; | 	return context; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| bool MMArchInitialiseUserSpace(MMSpace *space) { | bool MMArchInitialiseUserSpace(MMSpace *space, MMRegion *region) { | ||||||
|  | 	region->baseAddress = MM_USER_SPACE_START;  | ||||||
|  | 	region->pageCount = MM_USER_SPACE_SIZE / K_PAGE_SIZE; | ||||||
|  | 
 | ||||||
| 	if (!MMCommit(K_PAGE_SIZE, true)) { | 	if (!MMCommit(K_PAGE_SIZE, true)) { | ||||||
| 		return false; | 		return false; | ||||||
| 	} | 	} | ||||||
|  | @ -700,7 +706,7 @@ bool SetupInterruptRedirectionEntry(uintptr_t _line) { | ||||||
| 
 | 
 | ||||||
| 	for (uintptr_t i = 0; i < acpi.ioapicCount; i++) { | 	for (uintptr_t i = 0; i < acpi.ioapicCount; i++) { | ||||||
| 		ioApic = acpi.ioApics + i; | 		ioApic = acpi.ioApics + i; | ||||||
| 		if (line >= ioApic->gsiBase && line < (ioApic->gsiBase + (0xFF & (ioApic->ReadRegister(1) >> 16)))) { | 		if (line >= ioApic->gsiBase && line < (ioApic->gsiBase + (0xFF & (ACPIIoApicReadRegister(ioApic, 1) >> 16)))) { | ||||||
| 			foundIoApic = true; | 			foundIoApic = true; | ||||||
| 			line -= ioApic->gsiBase; | 			line -= ioApic->gsiBase; | ||||||
| 			break; | 			break; | ||||||
|  | @ -723,9 +729,9 @@ bool SetupInterruptRedirectionEntry(uintptr_t _line) { | ||||||
| 
 | 
 | ||||||
| 	// Send the interrupt to the processor that registered the interrupt.
 | 	// Send the interrupt to the processor that registered the interrupt.
 | ||||||
| 
 | 
 | ||||||
| 	ioApic->WriteRegister(redirectionTableIndex, 1 << 16); // Mask the interrupt while we modify the entry.
 | 	ACPIIoApicWriteRegister(ioApic, redirectionTableIndex, 1 << 16); // Mask the interrupt while we modify the entry.
 | ||||||
| 	ioApic->WriteRegister(redirectionTableIndex + 1, GetLocalStorage()->archCPU->apicID << 24);  | 	ACPIIoApicWriteRegister(ioApic, redirectionTableIndex + 1, GetLocalStorage()->archCPU->apicID << 24);  | ||||||
| 	ioApic->WriteRegister(redirectionTableIndex, redirectionEntry); | 	ACPIIoApicWriteRegister(ioApic, redirectionTableIndex, redirectionEntry); | ||||||
| 
 | 
 | ||||||
| 	alreadySetup |= 1 << _line; | 	alreadySetup |= 1 << _line; | ||||||
| 	return true; | 	return true; | ||||||
|  | @ -821,7 +827,7 @@ size_t ProcessorSendIPI(uintptr_t interrupt, bool nmi, int processorID) { | ||||||
| 	size_t ignored = 0; | 	size_t ignored = 0; | ||||||
| 
 | 
 | ||||||
| 	for (uintptr_t i = 0; i < acpi.processorCount; i++) { | 	for (uintptr_t i = 0; i < acpi.processorCount; i++) { | ||||||
| 		ACPIProcessor *processor = acpi.processors + i; | 		ArchCPU *processor = acpi.processors + i; | ||||||
| 
 | 
 | ||||||
| 		if (processorID != -1) { | 		if (processorID != -1) { | ||||||
| 			if (processorID != processor->kernelProcessorID) { | 			if (processorID != processor->kernelProcessorID) { | ||||||
|  | @ -837,11 +843,11 @@ size_t ProcessorSendIPI(uintptr_t interrupt, bool nmi, int processorID) { | ||||||
| 
 | 
 | ||||||
| 		uint32_t destination = acpi.processors[i].apicID << 24; | 		uint32_t destination = acpi.processors[i].apicID << 24; | ||||||
| 		uint32_t command = interrupt | (1 << 14) | (nmi ? 0x400 : 0); | 		uint32_t command = interrupt | (1 << 14) | (nmi ? 0x400 : 0); | ||||||
| 		acpi.lapic.WriteRegister(0x310 >> 2, destination); | 		ACPILapicWriteRegister(0x310 >> 2, destination); | ||||||
| 		acpi.lapic.WriteRegister(0x300 >> 2, command);  | 		ACPILapicWriteRegister(0x300 >> 2, command);  | ||||||
| 
 | 
 | ||||||
| 		// Wait for the interrupt to be sent.
 | 		// Wait for the interrupt to be sent.
 | ||||||
| 		while (acpi.lapic.ReadRegister(0x300 >> 2) & (1 << 12)); | 		while (ACPILapicReadRegister(0x300 >> 2) & (1 << 12)); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	return ignored; | 	return ignored; | ||||||
|  | @ -858,10 +864,10 @@ void ProcessorSendYieldIPI(Thread *thread) { | ||||||
| void ArchNextTimer(size_t ms) { | void ArchNextTimer(size_t ms) { | ||||||
| 	while (!scheduler.started);               // Wait until the scheduler is ready.
 | 	while (!scheduler.started);               // Wait until the scheduler is ready.
 | ||||||
| 	GetLocalStorage()->schedulerReady = true; // Make sure this CPU can be scheduled.
 | 	GetLocalStorage()->schedulerReady = true; // Make sure this CPU can be scheduled.
 | ||||||
| 	acpi.lapic.ArchNextTimer(ms);             // Set the next timer.
 | 	ACPILapicNextTimer(ms);                   // Set the next timer.
 | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| NewProcessorStorage AllocateNewProcessorStorage(ACPIProcessor *archCPU) { | NewProcessorStorage AllocateNewProcessorStorage(ArchCPU *archCPU) { | ||||||
| 	NewProcessorStorage storage = {}; | 	NewProcessorStorage storage = {}; | ||||||
| 	storage.local = (CPULocalStorage *) EsHeapAllocate(sizeof(CPULocalStorage), true, K_FIXED); | 	storage.local = (CPULocalStorage *) EsHeapAllocate(sizeof(CPULocalStorage), true, K_FIXED); | ||||||
| 	storage.gdt = (uint32_t *) MMMapPhysical(kernelMMSpace, MMPhysicalAllocate(MM_PHYSICAL_ALLOCATE_COMMIT_NOW), K_PAGE_SIZE, ES_FLAGS_DEFAULT); | 	storage.gdt = (uint32_t *) MMMapPhysical(kernelMMSpace, MMPhysicalAllocate(MM_PHYSICAL_ALLOCATE_COMMIT_NOW), K_PAGE_SIZE, ES_FLAGS_DEFAULT); | ||||||
|  | @ -882,19 +888,19 @@ void SetupProcessor2(NewProcessorStorage *storage) { | ||||||
| 			uint32_t value = 2 | (1 << 10); // NMI exception interrupt vector.
 | 			uint32_t value = 2 | (1 << 10); // NMI exception interrupt vector.
 | ||||||
| 			if (acpi.lapicNMIs[i].activeLow) value |= 1 << 13; | 			if (acpi.lapicNMIs[i].activeLow) value |= 1 << 13; | ||||||
| 			if (acpi.lapicNMIs[i].levelTriggered) value |= 1 << 15; | 			if (acpi.lapicNMIs[i].levelTriggered) value |= 1 << 15; | ||||||
| 			acpi.lapic.WriteRegister(registerIndex, value); | 			ACPILapicWriteRegister(registerIndex, value); | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	acpi.lapic.WriteRegister(0x350 >> 2, acpi.lapic.ReadRegister(0x350 >> 2) & ~(1 << 16)); | 	ACPILapicWriteRegister(0x350 >> 2, ACPILapicReadRegister(0x350 >> 2) & ~(1 << 16)); | ||||||
| 	acpi.lapic.WriteRegister(0x360 >> 2, acpi.lapic.ReadRegister(0x360 >> 2) & ~(1 << 16)); | 	ACPILapicWriteRegister(0x360 >> 2, ACPILapicReadRegister(0x360 >> 2) & ~(1 << 16)); | ||||||
| 	acpi.lapic.WriteRegister(0x080 >> 2, 0); | 	ACPILapicWriteRegister(0x080 >> 2, 0); | ||||||
| 	if (acpi.lapic.ReadRegister(0x30 >> 2) & 0x80000000) acpi.lapic.WriteRegister(0x410 >> 2, 0); | 	if (ACPILapicReadRegister(0x30 >> 2) & 0x80000000) ACPILapicWriteRegister(0x410 >> 2, 0); | ||||||
| 	acpi.lapic.EndOfInterrupt(); | 	ACPILapicEndOfInterrupt(); | ||||||
| 
 | 
 | ||||||
| 	// Configure the LAPIC's timer.
 | 	// Configure the LAPIC's timer.
 | ||||||
| 
 | 
 | ||||||
| 	acpi.lapic.WriteRegister(0x3E0 >> 2, 2); // Divisor = 16
 | 	ACPILapicWriteRegister(0x3E0 >> 2, 2); // Divisor = 16
 | ||||||
| 
 | 
 | ||||||
| 	// Create the processor's local storage.
 | 	// Create the processor's local storage.
 | ||||||
| 
 | 
 | ||||||
|  | @ -1130,7 +1136,7 @@ extern "C" void InterruptHandler(InterruptContext *context) { | ||||||
| 			__sync_fetch_and_sub(&callFunctionOnAllProcessorsRemaining, 1); | 			__sync_fetch_and_sub(&callFunctionOnAllProcessorsRemaining, 1); | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		acpi.lapic.EndOfInterrupt(); | 		ACPILapicEndOfInterrupt(); | ||||||
| 	} else if (interrupt >= INTERRUPT_VECTOR_MSI_START && interrupt < INTERRUPT_VECTOR_MSI_START + INTERRUPT_VECTOR_MSI_COUNT && local) { | 	} else if (interrupt >= INTERRUPT_VECTOR_MSI_START && interrupt < INTERRUPT_VECTOR_MSI_START + INTERRUPT_VECTOR_MSI_COUNT && local) { | ||||||
| 		KSpinlockAcquire(&irqHandlersLock); | 		KSpinlockAcquire(&irqHandlersLock); | ||||||
| 		MSIHandler handler = msiHandlers[interrupt - INTERRUPT_VECTOR_MSI_START]; | 		MSIHandler handler = msiHandlers[interrupt - INTERRUPT_VECTOR_MSI_START]; | ||||||
|  | @ -1143,7 +1149,7 @@ extern "C" void InterruptHandler(InterruptContext *context) { | ||||||
| 			handler.callback(interrupt - INTERRUPT_VECTOR_MSI_START, handler.context); | 			handler.callback(interrupt - INTERRUPT_VECTOR_MSI_START, handler.context); | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		acpi.lapic.EndOfInterrupt(); | 		ACPILapicEndOfInterrupt(); | ||||||
| 
 | 
 | ||||||
| 		if (local->irqSwitchThread && scheduler.started && local->schedulerReady) { | 		if (local->irqSwitchThread && scheduler.started && local->schedulerReady) { | ||||||
| 			scheduler.Yield(context); | 			scheduler.Yield(context); | ||||||
|  | @ -1203,7 +1209,7 @@ extern "C" void InterruptHandler(InterruptContext *context) { | ||||||
| 			GetLocalStorage()->inIRQ = false; | 			GetLocalStorage()->inIRQ = false; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		acpi.lapic.EndOfInterrupt(); | 		ACPILapicEndOfInterrupt(); | ||||||
| 
 | 
 | ||||||
| 		if (local->irqSwitchThread && scheduler.started && local->schedulerReady) { | 		if (local->irqSwitchThread && scheduler.started && local->schedulerReady) { | ||||||
| 			scheduler.Yield(context); | 			scheduler.Yield(context); | ||||||
|  | @ -1235,7 +1241,7 @@ extern "C" bool PostContextSwitch(InterruptContext *context, MMSpace *oldAddress | ||||||
| 		KernelLog(LOG_VERBOSE, "Arch", "executing new thread", "Executing new thread %x at %x\n", currentThread, context->rip); | 		KernelLog(LOG_VERBOSE, "Arch", "executing new thread", "Executing new thread %x at %x\n", currentThread, context->rip); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	acpi.lapic.EndOfInterrupt(); | 	ACPILapicEndOfInterrupt(); | ||||||
| 	ContextSanityCheck(context); | 	ContextSanityCheck(context); | ||||||
| 
 | 
 | ||||||
| 	if (ProcessorAreInterruptsEnabled()) { | 	if (ProcessorAreInterruptsEnabled()) { | ||||||
|  | @ -1312,4 +1318,47 @@ EsError ArchApplyRelocation(uintptr_t type, uint8_t *buffer, uintptr_t offset, u | ||||||
| 	return ES_SUCCESS; | 	return ES_SUCCESS; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | uintptr_t MMArchEarlyAllocatePage() { | ||||||
|  | 	uintptr_t i = physicalMemoryRegionsIndex; | ||||||
|  | 
 | ||||||
|  | 	while (!physicalMemoryRegions[i].pageCount) { | ||||||
|  | 		i++; | ||||||
|  | 
 | ||||||
|  | 		if (i == physicalMemoryRegionsCount) { | ||||||
|  | 			KernelPanic("MMArchEarlyAllocatePage - Expected more pages in physical regions.\n"); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	PhysicalMemoryRegion *region = physicalMemoryRegions + i; | ||||||
|  | 	uintptr_t returnValue = region->baseAddress; | ||||||
|  | 
 | ||||||
|  | 	region->baseAddress += K_PAGE_SIZE; | ||||||
|  | 	region->pageCount--; | ||||||
|  | 	physicalMemoryRegionsPagesCount--; | ||||||
|  | 	physicalMemoryRegionsIndex = i; | ||||||
|  | 
 | ||||||
|  | 	return returnValue; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | uint64_t MMArchPopulatePageFrameDatabase() { | ||||||
|  | 	uint64_t commitLimit = 0; | ||||||
|  | 
 | ||||||
|  | 	for (uintptr_t i = 0; i < physicalMemoryRegionsCount; i++) { | ||||||
|  | 		uintptr_t base = physicalMemoryRegions[i].baseAddress >> K_PAGE_BITS; | ||||||
|  | 		uintptr_t count = physicalMemoryRegions[i].pageCount; | ||||||
|  | 		commitLimit += count; | ||||||
|  | 
 | ||||||
|  | 		for (uintptr_t j = 0; j < count; j++) { | ||||||
|  | 			MMPhysicalInsertFreePagesNext(base + j); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	physicalMemoryRegionsPagesCount = 0; | ||||||
|  | 	return commitLimit; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | uintptr_t MMArchGetPhysicalMemoryHighest() { | ||||||
|  | 	return physicalMemoryHighest; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
|  | @ -77,6 +77,7 @@ extern "C" uintptr_t ProcessorGetRBP(); | ||||||
| extern "C" uint64_t ProcessorReadMXCSR(); | extern "C" uint64_t ProcessorReadMXCSR(); | ||||||
| extern "C" void ProcessorInstallTSS(uint32_t *gdt, uint32_t *tss); | extern "C" void ProcessorInstallTSS(uint32_t *gdt, uint32_t *tss); | ||||||
| extern "C" void ProcessorAPStartup(); | extern "C" void ProcessorAPStartup(); | ||||||
|  | extern "C" void ProcessorReset(); | ||||||
| 
 | 
 | ||||||
| extern "C" void SSSE3Framebuffer32To24Copy(volatile uint8_t *destination, volatile uint8_t *source, size_t pixelGroups); | extern "C" void SSSE3Framebuffer32To24Copy(volatile uint8_t *destination, volatile uint8_t *source, size_t pixelGroups); | ||||||
| extern "C" uintptr_t _KThreadTerminate; | extern "C" uintptr_t _KThreadTerminate; | ||||||
|  | @ -98,7 +99,7 @@ struct NewProcessorStorage { | ||||||
| 	uint32_t *gdt; | 	uint32_t *gdt; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| NewProcessorStorage AllocateNewProcessorStorage(struct ACPIProcessor *archCPU); | NewProcessorStorage AllocateNewProcessorStorage(struct ArchCPU *archCPU); | ||||||
| extern "C" void SetupProcessor2(struct NewProcessorStorage *); | extern "C" void SetupProcessor2(struct NewProcessorStorage *); | ||||||
| uintptr_t GetBootloaderInformationOffset(); | uintptr_t GetBootloaderInformationOffset(); | ||||||
| void ArchDelay1Ms(); // Spin for approximately 1ms. Use only during initialisation. Not thread-safe.
 | void ArchDelay1Ms(); // Spin for approximately 1ms. Use only during initialisation. Not thread-safe.
 | ||||||
|  | @ -108,4 +109,14 @@ uint8_t ACPIGetCenturyRegisterIndex(); | ||||||
| size_t ProcessorSendIPI(uintptr_t interrupt, bool nmi = false, int processorID = -1); // Returns the number of processors the IPI was *not* sent to.
 | size_t ProcessorSendIPI(uintptr_t interrupt, bool nmi = false, int processorID = -1); // Returns the number of processors the IPI was *not* sent to.
 | ||||||
| void ArchSetPCIIRQLine(uint8_t slot, uint8_t pin, uint8_t line); | void ArchSetPCIIRQLine(uint8_t slot, uint8_t pin, uint8_t line); | ||||||
| 
 | 
 | ||||||
|  | struct InterruptContext { | ||||||
|  | 	uint64_t cr2, ds; | ||||||
|  | 	uint8_t  fxsave[512 + 16]; | ||||||
|  | 	uint64_t _check, cr8; | ||||||
|  | 	uint64_t r15, r14, r13, r12, r11, r10, r9, r8; | ||||||
|  | 	uint64_t rbp, rdi, rsi, rdx, rcx, rbx, rax; | ||||||
|  | 	uint64_t interruptNumber, errorCode; | ||||||
|  | 	uint64_t rip, cs, flags, rsp, ss; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
|  | @ -892,11 +892,11 @@ MMArchSafeCopy: | ||||||
| 	mov	al,0 | 	mov	al,0 | ||||||
| 	ret | 	ret | ||||||
| 
 | 
 | ||||||
| [global ArchResetCPU] | [global ProcessorReset] | ||||||
| ArchResetCPU: | ProcessorReset: | ||||||
| 	in	al,0x64 | 	in	al,0x64 | ||||||
| 	test	al,2 | 	test	al,2 | ||||||
| 	jne	ArchResetCPU | 	jne	ProcessorReset | ||||||
| 	mov	al,0xFE | 	mov	al,0xFE | ||||||
| 	out	0x64,al | 	out	0x64,al | ||||||
| 	jmp	$ | 	jmp	$ | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue
	
	 nakst
						nakst