From 6fa375a9d84c0adbc150e12e001f11e8c704dbd8 Mon Sep 17 00:00:00 2001 From: nakst <> Date: Mon, 25 Oct 2021 10:01:56 +0100 Subject: [PATCH] kernel cleanup --- boot/x86/uefi_old.c | 404 ------------------------------------------- desktop/api.s | 22 +-- desktop/prefix.h | 2 +- drivers/acpi.cpp | 6 +- drivers/pci.cpp | 8 +- drivers/ps2.cpp | 2 +- kernel/elf.cpp | 33 +--- kernel/kernel.h | 169 ++++++++++++------ kernel/main.cpp | 2 +- kernel/memory.cpp | 45 +---- kernel/module.h | 63 +------ kernel/posix.cpp | 6 +- kernel/scheduler.cpp | 40 ++--- kernel/syscall.cpp | 16 +- kernel/terminal.cpp | 11 +- kernel/x86_64.cpp | 103 +++++------ kernel/x86_64.h | 43 ++++- kernel/x86_64.s | 48 +---- 18 files changed, 268 insertions(+), 755 deletions(-) delete mode 100644 boot/x86/uefi_old.c diff --git a/boot/x86/uefi_old.c b/boot/x86/uefi_old.c deleted file mode 100644 index ac5c2f4..0000000 --- a/boot/x86/uefi_old.c +++ /dev/null @@ -1,404 +0,0 @@ -#include -#include - -#define ENTRIES_PER_PAGE_TABLE (512) -#define ENTRIES_PER_PAGE_TABLE_BITS (9) -#define K_PAGE_SIZE (4096) -#define K_PAGE_BITS (12) - -typedef struct __attribute__((packed)) GDTData { - uint16_t length; - uint64_t address; -} GDTData; - -typedef struct MemoryRegion { - uintptr_t base, pages; -} MemoryRegion; - -#define MAX_MEMORY_REGIONS (1024) -MemoryRegion memoryRegions[1024]; -#define KERNEL_BUFFER_SIZE (1048576) -#define kernelBuffer ((char *) 0x200000) -#define IID_BUFFER_SIZE (64) -char iidBuffer[IID_BUFFER_SIZE]; -#define MEMORY_MAP_BUFFER_SIZE (16384) -char memoryMapBuffer[MEMORY_MAP_BUFFER_SIZE]; - -#define VESA_VM_INFO_ONLY -#define ARCH_64 -#include "../../kernel/graphics.cpp" -#include "../../kernel/elf.cpp" - -void ZeroMemory(void *pointer, uint64_t size) { - char *d = (char *) pointer; - - for (uintptr_t i = 0; i < size; i++) { - d[i] = 0; - } -} - -EFI_STATUS EFIAPI efi_main(EFI_HANDLE imageHandle, EFI_SYSTEM_TABLE *systemTable) { - UINTN mapKey; - uint32_t *framebuffer, horizontalResolution, verticalResolution, pixelsPerScanline; - InitializeLib(imageHandle, systemTable); - ElfHeader *header; - Print(L"Loading OS...\n"); - - // Make sure 0x100000 -> 0x300000 is identity mapped. - { - EFI_PHYSICAL_ADDRESS address = 0x100000; - - if (EFI_SUCCESS != uefi_call_wrapper(ST->BootServices->AllocatePages, 4, AllocateAddress, EfiLoaderData, 0x200, &address)) { - Print(L"Error: Could not map 0x100000 -> 0x180000.\n"); - while (1); - } - } - - // Find the RSDP. - { - for (uintptr_t i = 0; i < systemTable->NumberOfTableEntries; i++) { - EFI_CONFIGURATION_TABLE *entry = systemTable->ConfigurationTable + i; - if (entry->VendorGuid.Data1 == 0x8868E871 && entry->VendorGuid.Data2 == 0xE4F1 && entry->VendorGuid.Data3 == 0x11D3 - && entry->VendorGuid.Data4[0] == 0xBC && entry->VendorGuid.Data4[1] == 0x22 && entry->VendorGuid.Data4[2] == 0x00 - && entry->VendorGuid.Data4[3] == 0x80 && entry->VendorGuid.Data4[4] == 0xC7 && entry->VendorGuid.Data4[5] == 0x3C - && entry->VendorGuid.Data4[6] == 0x88 && entry->VendorGuid.Data4[7] == 0x81) { - *((uint64_t *) 0x107FE8) = (uint64_t) entry->VendorTable; - Print(L"The RSDP can be found at 0x%x.\n", entry->VendorTable); - } - } - } - - // Read the kernel, IID and loader files. - { - EFI_GUID loadedImageProtocolGUID = LOADED_IMAGE_PROTOCOL; - EFI_GUID simpleFilesystemProtocolGUID = SIMPLE_FILE_SYSTEM_PROTOCOL; - - EFI_LOADED_IMAGE_PROTOCOL *loadedImageProtocol; - EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *simpleFilesystemProtocol; - - EFI_FILE *filesystemRoot, *kernelFile, *iidFile, *loaderFile; - - UINTN size; - - if (EFI_SUCCESS != uefi_call_wrapper(ST->BootServices->OpenProtocol, 6, imageHandle, &loadedImageProtocolGUID, &loadedImageProtocol, imageHandle, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL)) { - Print(L"Error: Could not open protocol 1.\n"); - while (1); - } - - EFI_HANDLE deviceHandle = loadedImageProtocol->DeviceHandle; - - if (EFI_SUCCESS != uefi_call_wrapper(ST->BootServices->OpenProtocol, 6, deviceHandle, &simpleFilesystemProtocolGUID, &simpleFilesystemProtocol, imageHandle, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL)) { - Print(L"Error: Could not open procotol 2.\n"); - while (1); - } - - if (EFI_SUCCESS != uefi_call_wrapper(simpleFilesystemProtocol->OpenVolume, 2, simpleFilesystemProtocol, &filesystemRoot)) { - Print(L"Error: Could not open ESP volume.\n"); - while (1); - } - - if (EFI_SUCCESS != uefi_call_wrapper(filesystemRoot->Open, 5, filesystemRoot, &kernelFile, L"EssenceKernel.esx", EFI_FILE_MODE_READ, 0)) { - Print(L"Error: Could not open EssenceKernel.esx.\n"); - while (1); - } - - size = KERNEL_BUFFER_SIZE; - - if (EFI_SUCCESS != uefi_call_wrapper(kernelFile->Read, 3, kernelFile, &size, kernelBuffer)) { - Print(L"Error: Could not load EssenceKernel.esx.\n"); - while (1); - } - - Print(L"Kernel size: %d bytes\n", size); - - if (size == KERNEL_BUFFER_SIZE) { - Print(L"Kernel too large to fit into buffer.\n"); - while (1); - } - - if (EFI_SUCCESS != uefi_call_wrapper(filesystemRoot->Open, 5, filesystemRoot, &iidFile, L"EssenceIID.dat", EFI_FILE_MODE_READ, 0)) { - Print(L"Error: Could not open EssenceIID.dat.\n"); - while (1); - } - - size = IID_BUFFER_SIZE; - - if (EFI_SUCCESS != uefi_call_wrapper(iidFile->Read, 3, iidFile, &size, iidBuffer)) { - Print(L"Error: Could not load EssenceIID.dat.\n"); - while (1); - } - - if (EFI_SUCCESS != uefi_call_wrapper(filesystemRoot->Open, 5, filesystemRoot, &loaderFile, L"EssenceLoader.bin", EFI_FILE_MODE_READ, 0)) { - Print(L"Error: Could not open EssenceLoader.bin.\n"); - while (1); - } - - size = 0x80000; - - if (EFI_SUCCESS != uefi_call_wrapper(loaderFile->Read, 3, loaderFile, &size, (char *) 0x180000)) { - Print(L"Error: Could not load EssenceLoader.bin.\n"); - while (1); - } - } - -#if 0 - // Print the memory map. - { - UINTN descriptorSize, descriptorVersion, size = MEMORY_MAP_BUFFER_SIZE; - - if (EFI_SUCCESS != uefi_call_wrapper(ST->BootServices->GetMemoryMap, 5, &size, (EFI_MEMORY_DESCRIPTOR *) memoryMapBuffer, &mapKey, &descriptorSize, &descriptorVersion)) { - Print(L"Error: Could not get memory map.\n"); - while (1); - } - - WCHAR *memoryTypes[] = { - L"EfiReservedMemoryType", - L"EfiLoaderCode", - L"EfiLoaderData", - L"EfiBootServicesCode", - L"EfiBootServicesData", - L"EfiRuntimeServicesCode", - L"EfiRuntimeServicesData", - L"EfiConventionalMemory", - L"EfiUnusableMemory", - L"EfiACPIReclaimMemory", - L"EfiACPIMemoryNVS", - L"EfiMemoryMappedIO", - L"EfiMemoryMappedIOPortSpace", - L"EfiPalCode", - L"EfiMaxMemoryType", - }; - - for (uintptr_t i = 0; i < size / descriptorSize; i++) { - EFI_MEMORY_DESCRIPTOR *descriptor = (EFI_MEMORY_DESCRIPTOR *) (memoryMapBuffer + i * descriptorSize); - Print(L"memory %s: %llx -> %llx\n", memoryTypes[descriptor->Type], descriptor->PhysicalStart, descriptor->PhysicalStart + descriptor->NumberOfPages * 0x1000 - 1); - } - } -#endif - - // Get the graphics mode information. - { - EFI_GRAPHICS_OUTPUT_PROTOCOL *graphicsOutputProtocol; - EFI_GUID graphicsOutputProtocolGUID = EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID; - - if (EFI_SUCCESS != uefi_call_wrapper(ST->BootServices->LocateProtocol, 3, &graphicsOutputProtocolGUID, NULL, &graphicsOutputProtocol)) { - Print(L"Error: Could not open protocol 3.\n"); - while (1); - } - - int32_t desiredMode = -1; - - Print(L"Select a graphics mode:\n"); - - for (uint32_t i = 0; i < graphicsOutputProtocol->Mode->MaxMode; i++) { - EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *modeInformation; - UINTN modeInformationSize; - uefi_call_wrapper(graphicsOutputProtocol->QueryMode, 4, graphicsOutputProtocol, i, &modeInformationSize, &modeInformation); - - if (modeInformation->HorizontalResolution >= 800 && modeInformation->VerticalResolution >= 600) { - Print(L" %d: %d by %d\n", i + 1, modeInformation->HorizontalResolution, modeInformation->VerticalResolution); - } - } - - Print(L"> "); - - while (1) { - UINTN index; - uefi_call_wrapper(ST->BootServices->WaitForEvent, 3, 1, &systemTable->ConIn->WaitForKey, &index); - EFI_INPUT_KEY key; - uefi_call_wrapper(systemTable->ConIn->ReadKeyStroke, 2, systemTable->ConIn, &key); - - if (key.UnicodeChar >= '0' && key.UnicodeChar <= '9') { - if (desiredMode == -1) desiredMode = 0; - desiredMode = (desiredMode * 10) + key.UnicodeChar - '0'; - Print(L"%c", key.UnicodeChar); - } else if (key.UnicodeChar == 13) { - break; - } - } - - Print(L"\n"); - - if (desiredMode != -1) { - Print(L"Setting mode %d...\n", desiredMode); - desiredMode--; - - EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *modeInformation; - UINTN modeInformationSize; - uefi_call_wrapper(graphicsOutputProtocol->QueryMode, 4, graphicsOutputProtocol, desiredMode, &modeInformationSize, &modeInformation); - - horizontalResolution = modeInformation->HorizontalResolution; - verticalResolution = modeInformation->VerticalResolution; - pixelsPerScanline = modeInformation->PixelsPerScanLine; - - uefi_call_wrapper(graphicsOutputProtocol->SetMode, 2, graphicsOutputProtocol, desiredMode); - } else { - horizontalResolution = graphicsOutputProtocol->Mode->Info->HorizontalResolution; - verticalResolution = graphicsOutputProtocol->Mode->Info->VerticalResolution; - pixelsPerScanline = graphicsOutputProtocol->Mode->Info->PixelsPerScanLine; - } - - framebuffer = (uint32_t *) graphicsOutputProtocol->Mode->FrameBufferBase; - } - - // Get the memory map. - { - UINTN descriptorSize, descriptorVersion, size = MEMORY_MAP_BUFFER_SIZE; - - if (EFI_SUCCESS != uefi_call_wrapper(ST->BootServices->GetMemoryMap, 5, &size, (EFI_MEMORY_DESCRIPTOR *) memoryMapBuffer, &mapKey, &descriptorSize, &descriptorVersion)) { - Print(L"Error: Could not get memory map.\n"); - while (1); - } - - uintptr_t memoryRegionCount = 0; - - for (uintptr_t i = 0; i < size / descriptorSize && memoryRegionCount != MAX_MEMORY_REGIONS - 1; i++) { - EFI_MEMORY_DESCRIPTOR *descriptor = (EFI_MEMORY_DESCRIPTOR *) (memoryMapBuffer + i * descriptorSize); - - if (descriptor->Type == EfiConventionalMemory && descriptor->PhysicalStart >= 0x300000) { - memoryRegions[memoryRegionCount].base = descriptor->PhysicalStart; - memoryRegions[memoryRegionCount].pages = descriptor->NumberOfPages; - memoryRegionCount++; - } - } - - memoryRegions[memoryRegionCount].base = 0; - } - - // Exit boot services. - { - if (EFI_SUCCESS != uefi_call_wrapper(ST->BootServices->ExitBootServices, 2, imageHandle, mapKey)) { - Print(L"Error: Could not exit boot services.\n"); - while (1); - } - } - - // Identity map the first 3MB for the loader. - { - uint64_t *paging = (uint64_t *) 0x140000; - ZeroMemory(paging, 0x5000); - - paging[0x1FE] = 0x140003; - paging[0x000] = 0x141003; - paging[0x200] = 0x142003; - paging[0x400] = 0x143003; - paging[0x401] = 0x144003; - - for (uintptr_t i = 0; i < 0x400; i++) { - paging[0x600 + i] = (i * 0x1000) | 3; - } - } - - // Copy the installation ID across. - { - uint8_t *destination = (uint8_t *) (0x107FF0); - - for (uintptr_t i = 0; i < 16; i++) { - char c1 = iidBuffer[i * 3 + 0]; - char c2 = iidBuffer[i * 3 + 1]; - if (c1 >= '0' && c1 <= '9') c1 -= '0'; else c1 -= 'A' - 10; - if (c2 >= '0' && c2 <= '9') c2 -= '0'; else c2 -= 'A' - 10; - destination[i] = (c2) | ((c1) << 4); - } - } - - // Copy the graphics information across. - { - struct VESAVideoModeInformation *destination = (struct VESAVideoModeInformation *) (0x107000); - destination->widthPixels = horizontalResolution; - destination->heightPixels = verticalResolution; - destination->bufferPhysical = (uintptr_t) framebuffer; // TODO 64-bit framebuffers. - destination->bytesPerScanlineLinear = pixelsPerScanline * 4; - destination->bitsPerPixel = 32; - } - - // Allocate and map memory for the kernel. - { - uint64_t nextPageTable = 0x1C0000; - - header = (ElfHeader *) kernelBuffer; - ElfProgramHeader *programHeaders = (ElfProgramHeader *) (kernelBuffer + header->programHeaderTable); - uintptr_t programHeaderEntrySize = header->programHeaderEntrySize; - - for (uintptr_t i = 0; i < header->programHeaderEntries; i++) { - ElfProgramHeader *header = (ElfProgramHeader *) ((uint8_t *) programHeaders + programHeaderEntrySize * i); - if (header->type != 1) continue; - - uintptr_t pagesToAllocate = header->segmentSize >> 12; - if (header->segmentSize & 0xFFF) pagesToAllocate++; - uintptr_t physicalAddress = 0; - - for (uintptr_t j = 0; j < MAX_MEMORY_REGIONS; j++) { - MemoryRegion *region = memoryRegions + j; - if (!region->base) break; - if (region->pages < pagesToAllocate) continue; - physicalAddress = region->base; - region->pages -= pagesToAllocate; - region->base += pagesToAllocate << 12; - break; - } - - if (!physicalAddress) { - // TODO Error handling. - *((uint32_t *) framebuffer + 3) = 0xFFFF00FF; - while (1); - } - - for (uintptr_t j = 0; j < pagesToAllocate; j++, physicalAddress += 0x1000) { - uintptr_t virtualAddress = header->virtualAddress + j * K_PAGE_SIZE; - physicalAddress &= 0xFFFFFFFFFFFFF000; - virtualAddress &= 0x0000FFFFFFFFF000; - - uintptr_t indexL4 = (virtualAddress >> (K_PAGE_BITS + ENTRIES_PER_PAGE_TABLE_BITS * 3)) & (ENTRIES_PER_PAGE_TABLE - 1); - uintptr_t indexL3 = (virtualAddress >> (K_PAGE_BITS + ENTRIES_PER_PAGE_TABLE_BITS * 2)) & (ENTRIES_PER_PAGE_TABLE - 1); - uintptr_t indexL2 = (virtualAddress >> (K_PAGE_BITS + ENTRIES_PER_PAGE_TABLE_BITS * 1)) & (ENTRIES_PER_PAGE_TABLE - 1); - uintptr_t indexL1 = (virtualAddress >> (K_PAGE_BITS + ENTRIES_PER_PAGE_TABLE_BITS * 0)) & (ENTRIES_PER_PAGE_TABLE - 1); - - uint64_t *tableL4 = (uint64_t *) 0x140000; - - if (!(tableL4[indexL4] & 1)) { - tableL4[indexL4] = nextPageTable | 7; - ZeroMemory((void *) nextPageTable, K_PAGE_SIZE); - nextPageTable += K_PAGE_SIZE; - } - - uint64_t *tableL3 = (uint64_t *) (tableL4[indexL4] & ~(K_PAGE_SIZE - 1)); - - if (!(tableL3[indexL3] & 1)) { - tableL3[indexL3] = nextPageTable | 7; - ZeroMemory((void *) nextPageTable, K_PAGE_SIZE); - nextPageTable += K_PAGE_SIZE; - } - - uint64_t *tableL2 = (uint64_t *) (tableL3[indexL3] & ~(K_PAGE_SIZE - 1)); - - if (!(tableL2[indexL2] & 1)) { - tableL2[indexL2] = nextPageTable | 7; - ZeroMemory((void *) nextPageTable, K_PAGE_SIZE); - nextPageTable += K_PAGE_SIZE; - } - - uint64_t *tableL1 = (uint64_t *) (tableL2[indexL2] & ~(K_PAGE_SIZE - 1)); - uintptr_t value = physicalAddress | 3; - tableL1[indexL1] = value; - } - } - } - - // Copy the memory regions information across. - { - MemoryRegion *destination = (MemoryRegion *) 0x160000; - - for (uintptr_t i = 0; i < MAX_MEMORY_REGIONS; i++) { - destination[i] = memoryRegions[i]; - } - } - - // Start the loader. - { - ((void (*)()) 0x180000)(); - } - - while (1); - return EFI_SUCCESS; -} diff --git a/desktop/api.s b/desktop/api.s index 7086caa..d2f44b3 100644 --- a/desktop/api.s +++ b/desktop/api.s @@ -55,13 +55,6 @@ _EsCRTlongjmp: .return: ret -[global ProcessorReadTimeStamp] -ProcessorReadTimeStamp: - rdtsc - shl rdx,32 - or rax,rdx - ret - [global EsCRTsqrt] EsCRTsqrt: sqrtsd xmm0,xmm0 @@ -72,6 +65,13 @@ EsCRTsqrtf: sqrtss xmm0,xmm0 ret +[global ProcessorReadTimeStamp] +ProcessorReadTimeStamp: + rdtsc + shl rdx,32 + or rax,rdx + ret + [global ProcessorCheckStackAlignment] ProcessorCheckStackAlignment: mov rax,rsp @@ -94,11 +94,3 @@ ProcessorTLSRead: ProcessorTLSWrite: mov [fs:rdi],rsi ret - -[global __cyg_profile_func_enter] -__cyg_profile_func_enter: - ret - -[global __cyg_profile_func_exit] -__cyg_profile_func_exit: - ret diff --git a/desktop/prefix.h b/desktop/prefix.h index ca6a283..4e54f68 100644 --- a/desktop/prefix.h +++ b/desktop/prefix.h @@ -63,7 +63,7 @@ typedef struct EsElementPublic EsElementPublic; #ifdef ARCH_X86_64 #define ES_API_BASE ((void **) 0x1000) #define ES_SHARED_MEMORY_MAXIMUM_SIZE ((size_t) (1024) * 1024 * 1024 * 1024) -#define ES_PAGE_SIZE (4096) +#define ES_PAGE_SIZE ((uintptr_t) 4096) #define ES_PAGE_BITS (12) typedef struct EsCRTjmp_buf { diff --git a/drivers/acpi.cpp b/drivers/acpi.cpp index 73c82da..14cf420 100644 --- a/drivers/acpi.cpp +++ b/drivers/acpi.cpp @@ -142,6 +142,10 @@ void ACPILapic::WriteRegister(uint32_t reg, uint32_t value) { #ifdef ARCH_X86_COMMON uint64_t ArchGetTimeMs() { + // Update the time stamp counter synchronization value. + timeStampCounterSynchronizationValue = ((timeStampCounterSynchronizationValue & 0x8000000000000000) + ^ 0x8000000000000000) | ProcessorReadTimeStamp(); + if (acpi.hpetBaseAddress && acpi.hpetPeriod) { __int128 fsToMs = 1000000000000; __int128 reading = acpi.hpetBaseAddress[30]; @@ -724,7 +728,7 @@ void ACPIEnumeratePRTEntries(ACPI_HANDLE pciBus) { } else if (table->Pin > 3) { KernelLog(LOG_ERROR, "ACPI", "unexpected pin", "Pin %d was larger than expected.\n", table->Pin); } else { - pciIRQLines[table->Address >> 16][table->Pin] = irq; + ArchSetPCIIRQLine(table->Address >> 16, table->Pin, irq); } } } diff --git a/drivers/pci.cpp b/drivers/pci.cpp index 4515e47..17fb934 100644 --- a/drivers/pci.cpp +++ b/drivers/pci.cpp @@ -214,7 +214,13 @@ bool KPCIDevice::EnableSingleInterrupt(KIRQHandler irqHandler, void *context, co // If we booted from EFI, we need to get the interrupt line from ACPI. // See the comment in InterruptHandler for what happens when passing -1. - if (KRegisterIRQ(KBootedFromEFI() ? -1 : interruptLine, irqHandler, context, cOwnerName, this)) { + intptr_t line = interruptLine; +#ifdef ARCH_X86_COMMON + extern uint32_t bootloaderID; + if (bootloaderID == 2) line = -1; +#endif + + if (KRegisterIRQ(line, irqHandler, context, cOwnerName, this)) { return true; } diff --git a/drivers/ps2.cpp b/drivers/ps2.cpp index 0248aaf..58beb2e 100644 --- a/drivers/ps2.cpp +++ b/drivers/ps2.cpp @@ -303,7 +303,7 @@ int PS2ReadKey() { } int KWaitKey() { - if (!ps2.channels) ProcessorHalt(); + if (!ps2.channels) return -1; int scancode; while (!(scancode = PS2ReadKey())); return scancode; diff --git a/kernel/elf.cpp b/kernel/elf.cpp index 2d5cbc6..8446f04 100644 --- a/kernel/elf.cpp +++ b/kernel/elf.cpp @@ -139,14 +139,9 @@ EsError KLoadELF(KNode *node, KLoadedExecutable *executable) { } } -#ifdef ARCH_X86_64 - if (header.mapAddress > 0x8000000000000000UL || header.mapAddress < 0x1000 || fileSize > 0x1000000000000UL - || header.mapAddress & (K_PAGE_SIZE - 1)) { + if (ArchCheckBundleHeader() || header.mapAddress & (K_PAGE_SIZE - 1)) { return ES_ERROR_UNSUPPORTED_EXECUTABLE; } -#else -#error Unimplemented. -#endif if (header.version != 1) { return ES_ERROR_UNSUPPORTED_EXECUTABLE; @@ -162,12 +157,7 @@ EsError KLoadELF(KNode *node, KLoadedExecutable *executable) { // Look for the executable in the bundle. -#ifdef ARCH_X86_64 - uint64_t name = CalculateCRC64(EsLiteral("$Executables/x86_64")); -#else -#error Unimplemented. -#endif - + uint64_t name = CalculateCRC64(EsLiteral("$Executables/" K_ARCH_NAME)); BundleFile *files = (BundleFile *) ((BundleHeader *) header.mapAddress + 1); bool found = false; @@ -214,13 +204,9 @@ EsError KLoadELF(KNode *node, KLoadedExecutable *executable) { ElfProgramHeader *header = (ElfProgramHeader *) ((uint8_t *) programHeaders + programHeaderEntrySize * i); if (header->type == 1 /* PT_LOAD */) { -#ifdef ARCH_X86_64 - if (header->virtualAddress > 0x8000000000000000UL || header->virtualAddress < 0x1000 || header->segmentSize > 0x1000000000000UL) { + if (ArchCheckELFHeader()) { return ES_ERROR_UNSUPPORTED_EXECUTABLE; } -#else -#error Unimplemented. -#endif #if 0 EsPrint("FileOffset %x VirtualAddress %x SegmentSize %x DataInFile %x\n", @@ -403,17 +389,8 @@ EsError KLoadELFModule(KModule *module) { // EsPrint("\t%d: %z (%x), %d, %x, %x\n", i, buffer + symbol->name + strings->offset, symbol->value, type, offset, relocation->addend); uintptr_t result = symbol->value + relocation->addend; - -#ifdef ARCH_X86_64 - if (type == 0) {} - else if (type == 10 /* R_X86_64_32 */) *((uint32_t *) (buffer + offset)) = result; - else if (type == 11 /* R_X86_64_32S */) *((uint32_t *) (buffer + offset)) = result; - else if (type == 1 /* R_X86_64_64 */) *((uint64_t *) (buffer + offset)) = result; - else if (type == 2 /* R_X86_64_PC32 */) *((uint32_t *) (buffer + offset)) = result - ((uint64_t) buffer + offset); - else if (type == 24 /* R_X86_64_PC64 */) *((uint64_t *) (buffer + offset)) = result - ((uint64_t) buffer + offset); - else if (type == 4 /* R_X86_64_PLT32 */) *((uint32_t *) (buffer + offset)) = result - ((uint64_t) buffer + offset); -#endif - else return ES_ERROR_UNSUPPORTED_FEATURE; + EsError error = ArchApplyRelocation(type, buffer, offset, result); + if (error != ES_SUCCESS) return error; } } diff --git a/kernel/kernel.h b/kernel/kernel.h index 007122c..14259ae 100644 --- a/kernel/kernel.h +++ b/kernel/kernel.h @@ -4,7 +4,9 @@ #define K_PRIVATE #include "module.h" -////////////////////////////////// +// --------------------------------------------------------------------------------------------------------------- +// Constants. +// --------------------------------------------------------------------------------------------------------------- // TODO Determine the best values for these constants. @@ -62,11 +64,9 @@ #define PHYSICAL_MEMORY_MANIPULATION_REGION_PAGES (16) #define POOL_CACHE_COUNT (16) -////////////////////////////////// - -#include - -#define EsAssertionFailure(file, line) KernelPanic("%z:%d - EsAssertionFailure called.\n", file, line) +// --------------------------------------------------------------------------------------------------------------- +// Core definitions. +// --------------------------------------------------------------------------------------------------------------- #ifdef ARCH_X86_64 #include "x86_64.cpp" @@ -98,93 +98,141 @@ struct CPULocalStorage { volatile uint8_t asyncTasksRead, asyncTasksWrite; }; -////////////////////////////////// +struct PhysicalMemoryRegion { + uint64_t baseAddress; + uint64_t pageCount; +}; void KernelInitialise(); void KernelShutdown(uintptr_t action); -void ArchInitialise(); -void ArchShutdown(uintptr_t action); - -extern "C" void ArchResetCPU(); -extern "C" void ArchSpeakerBeep(); -extern "C" void ArchNextTimer(size_t ms); // Schedule the next TIMER_INTERRUPT. -extern "C" uint64_t ArchGetTimeMs(); // Called by the scheduler on the boot processor every context switch. -InterruptContext *ArchInitialiseThread(uintptr_t kernelStack, uintptr_t kernelStackSize, struct Thread *thread, - uintptr_t startAddress, uintptr_t argument1, uintptr_t argument2, - bool userland, uintptr_t stack, uintptr_t userStackSize); - -void StartDebugOutput(); - uint64_t timeStampTicksPerMs; - EsUniqueIdentifier installationID; // The identifier of this OS installation, given to us by the bootloader. -struct Process *desktopProcess; -KSpinlock ipiLock; +// --------------------------------------------------------------------------------------------------------------- +// Architecture specific layer definitions. +// --------------------------------------------------------------------------------------------------------------- -////////////////////////////////// +extern "C" { + void ArchInitialise(); + void ArchShutdown(uintptr_t action); + void ArchNextTimer(size_t ms); // Schedule the next TIMER_INTERRUPT. + uint64_t ArchGetTimeMs(); // Called by the scheduler on the boot processor every context switch. + InterruptContext *ArchInitialiseThread(uintptr_t kernelStack, uintptr_t kernelStackSize, struct Thread *thread, + uintptr_t startAddress, uintptr_t argument1, uintptr_t argument2, + 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, + struct Thread *newThread, struct MMSpace *oldAddressSpace); + + 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. + 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); + 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 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. + void MMArchFreeVAS(MMSpace *space); + void MMArchFinalizeVAS(MMSpace *space); + + void ProcessorDisableInterrupts(); + void ProcessorEnableInterrupts(); + bool ProcessorAreInterruptsEnabled(); + + void ArchResetCPU(); + void ProcessorHalt(); + void ProcessorSendYieldIPI(Thread *thread); + void ProcessorFakeTimerInterrupt(); + + void ProcessorInvalidatePage(uintptr_t virtualAddress); + void ProcessorInvalidateAllPages(); + void ProcessorFlushCodeCache(); + void ProcessorFlushCache(); + + void ProcessorSetLocalStorage(struct CPULocalStorage *cls); + void ProcessorSetThreadStorage(uintptr_t tls); + void ProcessorSetAddressSpace(struct MMArchVAS *virtualAddressSpace); // Need to call MMSpaceOpenReference/MMSpaceCloseReference if using this. + + uint64_t ProcessorReadTimeStamp(); + + struct CPULocalStorage *GetLocalStorage(); + 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: + // 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); + // void KPCIWriteConfig(uint8_t bus, uint8_t device, uint8_t function, uint8_t offset, uint32_t value, int size); + // bool KRegisterIRQ(intptr_t interruptIndex, KIRQHandler handler, void *context, const char *cOwnerName, struct KPCIDevice *pciDevice); + // KMSIInformation KRegisterMSI(KIRQHandler handler, void *context, const char *cOwnerName); + // void KUnregisterMSI(uintptr_t tag); +} #endif +// --------------------------------------------------------------------------------------------------------------- +// Kernel components. +// --------------------------------------------------------------------------------------------------------------- + #include #include #include #include "memory.cpp" - -#ifndef IMPLEMENTATION -#include -#include -#else -#define ARRAY_IMPLEMENTATION_ONLY -#include -#include -#endif - #include "objects.cpp" #include "syscall.cpp" #include "scheduler.cpp" #include "synchronisation.cpp" -#include "drivers.cpp" +#include "cache.cpp" #include "elf.cpp" #include "graphics.cpp" -#include "cache.cpp" #include "files.cpp" #include "windows.cpp" #include "networking.cpp" -#include "terminal.cpp" +#include "drivers.cpp" #ifdef ENABLE_POSIX_SUBSYSTEM #include "posix.cpp" #endif +#ifndef IMPLEMENTATION +#define ARRAY_IMPLEMENTATION_ONLY +#include +#include +#include +#include +#include +#endif + +// --------------------------------------------------------------------------------------------------------------- +// Miscellaneous. +// --------------------------------------------------------------------------------------------------------------- + #ifdef IMPLEMENTATION -////////////////////////////////// - -extern "C" uint64_t KGetTimeInMs() { - if (!timeStampTicksPerMs) return 0; +uint64_t KGetTimeInMs() { return scheduler.timeMs; } -uint64_t KGetTimeStampTicksPerMs() { - return timeStampTicksPerMs; -} - -uint64_t KGetTimeStampTicksPerUs() { - return timeStampTicksPerMs / 1000; -} - -bool KInIRQ() { - return GetLocalStorage()->inIRQ; -} - bool KBootedFromEFI() { extern uint32_t bootloaderID; return bootloaderID == 2; } +bool KInIRQ() { + return GetLocalStorage()->inIRQ; +} + void KSwitchThreadAfterIRQ() { GetLocalStorage()->irqSwitchThread = true; } @@ -193,12 +241,19 @@ EsUniqueIdentifier KGetBootIdentifier() { return installationID; } -////////////////////////////////// +void EsAssertionFailure(const char *file, int line) { + KernelPanic("%z:%d - EsAssertionFailure called.\n", file, line); +} -#ifdef ARCH_X86_64 +#endif + +// --------------------------------------------------------------------------------------------------------------- +// Architecture specific layer implementation. +// --------------------------------------------------------------------------------------------------------------- + +#if defined(ARCH_X86_64) && defined(IMPLEMENTATION) #include "x86_64.h" +#include "terminal.cpp" #include #include "x86_64.cpp" #endif - -#endif diff --git a/kernel/main.cpp b/kernel/main.cpp index eed19b2..5ba3a5a 100644 --- a/kernel/main.cpp +++ b/kernel/main.cpp @@ -10,7 +10,7 @@ #include "kernel.h" extern "C" void KernelMain() { - scheduler.SpawnProcess(PROCESS_KERNEL); // Spawn the kernel process. + kernelProcess = scheduler.SpawnProcess(PROCESS_KERNEL); // Spawn the kernel process. ArchInitialise(); // Start processors and initialise CPULocalStorage. scheduler.started = true; // Start the pre-emptive scheduler. // Continues in KernelInitialise. diff --git a/kernel/memory.cpp b/kernel/memory.cpp index 52db737..833e18e 100644 --- a/kernel/memory.cpp +++ b/kernel/memory.cpp @@ -66,7 +66,7 @@ struct MMRegion { // One per process. struct MMSpace { - VIRTUAL_ADDRESS_SPACE_DATA(); // Architecture specific data. + MMArchVAS data; // Architecture specific data. AVLTree // Key = freeRegionsBase, // Base address @@ -173,7 +173,7 @@ struct PMM { KSpinlock pmManipulationProcessorLock; void *pmManipulationRegion; - Thread *zeroPageThread, *balanceThread; + Thread *zeroPageThread; KEvent zeroPageEvent; LinkedList objectCacheList; @@ -191,7 +191,7 @@ struct PMM { // These variables will be cleared if the object they point to is removed. // See MMUnreserve and Scheduler::RemoveProcess. - Process *nextProcessToBalance; + struct Process *nextProcessToBalance; MMRegion *nextRegionToBalance; uintptr_t balanceResumePosition; }; @@ -247,22 +247,6 @@ extern MMSpace _kernelMMSpace, _coreMMSpace; #define MM_SHARED_ENTRY_PRESENT (1) -// Architecture-dependent functions. - -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 MMArchInvalidatePages(uintptr_t virtualAddressStart, uintptr_t pageCount); -bool MMArchHandlePageFault(uintptr_t address, uint32_t flags); -uintptr_t MMArchTranslateAddress(MMSpace *space, uintptr_t virtualAddress, bool writeAccess); -void MMArchInitialiseVAS(); -bool MMArchInitialiseUserSpace(MMSpace *space); -bool MMArchCommitPageTables(MMSpace *space, MMRegion *region); -bool MMArchMakePageWritable(MMSpace *space, uintptr_t virtualAddress); -bool MMArchIsBufferInUserRange(uintptr_t baseAddress, size_t byteCount); -extern "C" bool MMArchSafeCopy(uintptr_t destinationAddress, uintptr_t sourceAddress, size_t byteCount); // Returns false if a page fault occured during the copy. -void MMFreeVAS(MMSpace *space); -void MMFinalizeVAS(MMSpace *space); - // Forward declarations. bool MMHandlePageFault(MMSpace *space, uintptr_t address, unsigned flags); @@ -293,22 +277,6 @@ MMRegion *MMFindRegion(MMSpace *space, uintptr_t address); void *MMMapFile(MMSpace *space, struct FSFile *node, EsFileOffset offset, size_t bytes, int protection, void *baseAddress, size_t zeroedBytes = 0, uint32_t additionalFlags = ES_FLAGS_DEFAULT); -// Physical memory information from the bootloader. - -struct PhysicalMemoryRegion { - uint64_t baseAddress; - - // The memory map the BIOS provides gives the information in pages. - uint64_t pageCount; -}; - -extern PhysicalMemoryRegion *physicalMemoryRegions; -extern size_t physicalMemoryRegionsCount; -extern size_t physicalMemoryRegionsPagesCount; -extern size_t physicalMemoryOriginalPagesCount; -extern size_t physicalMemoryRegionsIndex; -extern uintptr_t physicalMemoryHighest; - // Physical memory manipulation. void PMZero(uintptr_t *pages, size_t pageCount, @@ -1649,7 +1617,7 @@ void MMSpaceDestroy(MMSpace *space) { EsHeapFree(item->thisItem, sizeof(MMRegion), K_CORE); } - MMFreeVAS(space); + MMArchFreeVAS(space); } bool MMUnmapFilePage(uintptr_t frameNumber) { @@ -2301,7 +2269,7 @@ void MMSpaceCloseReference(MMSpace *space) { KRegisterAsyncTask([] (EsGeneric _space) { MMSpace *space = (MMSpace *) _space.p; - MMFinalizeVAS(space); + MMArchFinalizeVAS(space); scheduler.mmSpacePool.Remove(space); }, space); } @@ -2374,8 +2342,7 @@ void MMInitialise() { pmm.zeroPageEvent.autoReset = true; MMCommit(PHYSICAL_MEMORY_MANIPULATION_REGION_PAGES * K_PAGE_SIZE, true); pmm.zeroPageThread = scheduler.SpawnThread("MMZero", (uintptr_t) MMZeroPageThread, 0, SPAWN_THREAD_LOW_PRIORITY); - pmm.balanceThread = scheduler.SpawnThread("MMBalance", (uintptr_t) MMBalanceThread, 0, ES_FLAGS_DEFAULT); - pmm.balanceThread->isPageGenerator = true; + scheduler.SpawnThread("MMBalance", (uintptr_t) MMBalanceThread, 0, ES_FLAGS_DEFAULT)->isPageGenerator = true; scheduler.SpawnThread("MMObjTrim", (uintptr_t) MMObjectCacheTrimThread, 0, ES_FLAGS_DEFAULT); } diff --git a/kernel/module.h b/kernel/module.h index 9c396de..21a9743 100644 --- a/kernel/module.h +++ b/kernel/module.h @@ -78,6 +78,8 @@ void KernelLog(KLogLevel level, const char *subsystem, const char *event, const void KernelPanic(const char *format, ...); void EsPrint(const char *format, ...); +void StartDebugOutput(); // Causes the output to be directly displayed on the screen. For debugging only. + #define EsPanic KernelPanic // --------------------------------------------------------------------------------------------------------------- @@ -133,72 +135,33 @@ void KRegisterAsyncTask(KAsyncTaskCallback callback, EsGeneric argument, bool ne #endif // --------------------------------------------------------------------------------------------------------------- -// Processor instruction wrappers. +// Processor IO. // --------------------------------------------------------------------------------------------------------------- -extern "C" struct CPULocalStorage *GetLocalStorage(); -extern "C" struct Thread *GetCurrentThread(); - -extern "C" void ProcessorDisableInterrupts(); -extern "C" void ProcessorEnableInterrupts(); -extern "C" bool ProcessorAreInterruptsEnabled(); -extern "C" void ProcessorHalt(); -extern "C" void ProcessorIdle(); extern "C" void ProcessorOut8(uint16_t port, uint8_t value); extern "C" uint8_t ProcessorIn8(uint16_t port); extern "C" void ProcessorOut16(uint16_t port, uint16_t value); extern "C" uint16_t ProcessorIn16(uint16_t port); extern "C" void ProcessorOut32(uint16_t port, uint32_t value); extern "C" uint32_t ProcessorIn32(uint16_t port); -extern "C" void ProcessorInvalidatePage(uintptr_t virtualAddress); -extern "C" void ProcessorInvalidateAllPages(); -extern "C" void ProcessorAPStartup(); -extern "C" void ProcessorMagicBreakpoint(...); -extern "C" void ProcessorBreakpointHelper(...); -extern "C" void ProcessorSetLocalStorage(struct CPULocalStorage *cls); -extern "C" void ProcessorSetThreadStorage(uintptr_t tls); -extern "C" size_t ProcessorSendIPI(uintptr_t interrupt, bool nmi = false, int processorID = -1); // Returns the number of processors the IPI was *not* sent to. -extern "C" void ProcessorDebugOutputByte(uint8_t byte); -extern "C" void ProcessorFakeTimerInterrupt(); -extern "C" uint64_t ProcessorReadTimeStamp(); -extern "C" void DoContextSwitch(struct InterruptContext *context, uintptr_t virtualAddressSpace, uintptr_t threadKernelStack, - struct Thread *newThread, struct MMSpace *oldAddressSpace); -extern "C" void ProcessorSetAddressSpace(uintptr_t virtualAddressSpaceIdentifier); // Need to call MMSpaceOpenReference/MMSpaceCloseReference if using this. -extern "C" uintptr_t ProcessorGetAddressSpace(); -extern "C" void ProcessorFlushCodeCache(); -extern "C" void ProcessorFlushCache(); - -#ifdef ARCH_X86_64 -extern "C" uintptr_t ProcessorGetRSP(); -extern "C" uintptr_t ProcessorGetRBP(); -extern "C" uint64_t ProcessorReadMXCSR(); -#endif // --------------------------------------------------------------------------------------------------------------- // Kernel core. // --------------------------------------------------------------------------------------------------------------- -extern "C" uint64_t KGetTimeInMs(); // Scheduler time. - +uint64_t KGetTimeInMs(); // Scheduler time. +EsUniqueIdentifier KGetBootIdentifier(); size_t KGetCPUCount(); -CPULocalStorage *KGetCPULocal(uintptr_t index); +struct CPULocalStorage *KGetCPULocal(uintptr_t index); uint64_t KCPUCurrentID(); -uint64_t KGetTimeStampTicksPerMs(); -uint64_t KGetTimeStampTicksPerUs(); - -bool KBootedFromEFI(); bool KInIRQ(); void KSwitchThreadAfterIRQ(); - void KDebugKeyPressed(); -int KWaitKey(); #ifdef ARCH_X86_COMMON void KPS2SafeToInitialise(); #endif -EsUniqueIdentifier KGetBootIdentifier(); - struct KTimeout { uint64_t end; inline KTimeout(int ms) { end = KGetTimeInMs() + ms; } @@ -364,15 +327,8 @@ void KTimerRemove(KTimer *timer); // Timers with callbacks cannot be removed (it // Memory manager. // --------------------------------------------------------------------------------------------------------------- -#ifdef ARCH_X86_64 -#define K_PAGE_BITS (12) -#define K_PAGE_SIZE ((uintptr_t) 1 << K_PAGE_BITS) -#define K_USER_ADDRESS_SPACE_START (0x0000000000000000ULL) -#define K_USER_ADDRESS_SPACE_END (0x0000800000000000ULL) -#define K_KERNEL_ADDRESS_SPACE_START (0xFFFF800000000000ULL) -#define K_KERNEL_ADDRESS_SPACE_END (0xFFFFFFFFFFFFFFFFULL) -#define K_STACK_GROWS_DOWN -#endif +#define K_PAGE_BITS ES_PAGE_BITS +#define K_PAGE_SIZE ES_PAGE_SIZE struct MMSpace; MMSpace *MMGetKernelSpace(); @@ -399,9 +355,6 @@ uint64_t MMNumberOfUsablePhysicalPages(); // Returns 0 if not mapped. Rounds address down to nearest page. uintptr_t MMArchTranslateAddress(MMSpace *space, uintptr_t virtualAddress, bool writeAccess = false /* if true, return 0 if address not writable */); -// Must be done with interrupts disabled; does not invalidate the page on other processors. -void MMArchRemap(MMSpace *space, const void *virtualAddress, uintptr_t newPhysicalAddress); - #define MM_PHYSICAL_ALLOCATE_CAN_FAIL (1 << 0) // Don't panic if the allocation fails. #define MM_PHYSICAL_ALLOCATE_COMMIT_NOW (1 << 1) // Commit (fixed) the allocated pages. #define MM_PHYSICAL_ALLOCATE_ZEROED (1 << 2) // Zero the pages. diff --git a/kernel/posix.cpp b/kernel/posix.cpp index 740dea1..1b665a6 100644 --- a/kernel/posix.cpp +++ b/kernel/posix.cpp @@ -468,7 +468,7 @@ namespace POSIX { // Save the state of the user's stack. currentThread->posixData->forkStackSize = currentThread->userStackCommit; currentThread->posixData->forkStack = (void *) EsHeapAllocate(currentThread->posixData->forkStackSize, false, K_PAGED); -#ifdef K_STACK_GROWS_DOWN +#ifdef K_ARCH_STACK_GROWS_DOWN EsMemoryCopy(currentThread->posixData->forkStack, (void *) (currentThread->userStackBase + currentThread->userStackReserve - currentThread->posixData->forkStackSize), currentThread->posixData->forkStackSize); @@ -533,7 +533,7 @@ namespace POSIX { CloseHandleToObject(process->executableMainThread, KERNEL_OBJECT_THREAD); // Restore the state of our stack. -#ifdef K_STACK_GROWS_DOWN +#ifdef K_ARCH_STACK_GROWS_DOWN EsMemoryCopy((void *) (currentThread->userStackBase + currentThread->userStackReserve - currentThread->posixData->forkStackSize), currentThread->posixData->forkStack, currentThread->posixData->forkStackSize); #else @@ -560,7 +560,7 @@ namespace POSIX { // Are we vforking? if (currentThread->posixData->forkStack) { // Restore the state of our stack. -#ifdef K_STACK_GROWS_DOWN +#ifdef K_ARCH_STACK_GROWS_DOWN EsMemoryCopy((void *) (currentThread->userStackBase + currentThread->userStackReserve - currentThread->posixData->forkStackSize), currentThread->posixData->forkStack, currentThread->posixData->forkStackSize); #else diff --git a/kernel/scheduler.cpp b/kernel/scheduler.cpp index 83d1559..d871c4b 100644 --- a/kernel/scheduler.cpp +++ b/kernel/scheduler.cpp @@ -163,9 +163,6 @@ struct Process { #endif }; -Process _kernelProcess; -Process *kernelProcess = &_kernelProcess; - struct Scheduler { // External API: @@ -176,7 +173,7 @@ struct Scheduler { #define SPAWN_THREAD_LOW_PRIORITY (4) #define SPAWN_THREAD_PAUSED (8) Thread *SpawnThread(const char *cName, uintptr_t startAddress, uintptr_t argument1 = 0, - unsigned flags = ES_FLAGS_DEFAULT, Process *process = kernelProcess, uintptr_t argument2 = 0); + uint32_t flags = ES_FLAGS_DEFAULT, Process *process = nullptr, uintptr_t argument2 = 0); void TerminateThread(Thread *thread, bool lockAlreadyAcquired = false); void PauseThread(Thread *thread, bool resume /*true to resume, false to pause*/, bool lockAlreadyAcquired = false); @@ -238,6 +235,10 @@ struct Scheduler { #endif }; +Process _kernelProcess; +Process *kernelProcess = &_kernelProcess; +Process *desktopProcess; + extern Scheduler scheduler; #endif @@ -364,9 +365,13 @@ void Scheduler::InsertNewThread(Thread *thread, bool addToActiveList, Process *o allThreads.InsertStart(&thread->allItem); } -Thread *Scheduler::SpawnThread(const char *cName, uintptr_t startAddress, uintptr_t argument1, unsigned flags, Process *process, uintptr_t argument2) { +Thread *Scheduler::SpawnThread(const char *cName, uintptr_t startAddress, uintptr_t argument1, uint32_t flags, Process *process, uintptr_t argument2) { bool userland = flags & SPAWN_THREAD_USERLAND; + if (!process) { + process = kernelProcess; + } + if (userland && process == kernelProcess) { KernelPanic("Scheduler::SpawnThread - Cannot add userland thread to kernel process.\n"); } @@ -403,7 +408,7 @@ Thread *Scheduler::SpawnThread(const char *cName, uintptr_t startAddress, uintpt MMRegion *region = MMFindAndPinRegion(process->vmm, stack, userStackReserve); KMutexAcquire(&process->vmm->reserveMutex); -#ifdef K_STACK_GROWS_DOWN +#ifdef K_ARCH_STACK_GROWS_DOWN bool success = MMCommitRange(process->vmm, region, (userStackReserve - userStackCommit) / K_PAGE_SIZE, userStackCommit / K_PAGE_SIZE); #else bool success = MMCommitRange(process->vmm, region, 0, userStackCommit / K_PAGE_SIZE); @@ -779,7 +784,7 @@ void Thread::SetAddressSpace(MMSpace *space) { temporaryAddressSpace = space; MMSpace *newSpace = space ?: kernelMMSpace; MMSpaceOpenReference(newSpace); - ProcessorSetAddressSpace(VIRTUAL_ADDRESS_SPACE_IDENTIFIER(newSpace)); + ProcessorSetAddressSpace(&newSpace->data); KSpinlockRelease(&scheduler.lock); MMSpaceCloseReference(oldSpace); } @@ -1020,11 +1025,7 @@ void Scheduler::PauseThread(Thread *thread, bool resume, bool lockAlreadyAcquire } else { // The thread is executing, but on a different processor. // Send them an IPI to stop. - thread->receivedYieldIPI = false; - KSpinlockAcquire(&ipiLock); - ProcessorSendIPI(YIELD_IPI, false); - KSpinlockRelease(&ipiLock); - while (!thread->receivedYieldIPI); // Spin until the thread gets the IPI. + ProcessorSendYieldIPI(thread); // TODO The interrupt context might not be set at this point. } } else { @@ -1349,29 +1350,18 @@ void Scheduler::Yield(InterruptContext *context) { else newThread->process->cpuTimeSlices++; // Prepare the next timer interrupt. - uint64_t nextTimer = 1; - ArchNextTimer(nextTimer); + ArchNextTimer(1 /* ms */); if (!local->processorID) { // Update the scheduler's time. -#if 1 timeMs = ArchGetTimeMs(); globalData->schedulerTimeMs = timeMs; -#else - // This drifts by roughly a second every minute. - timeMs = ProcessorReadTimeStamp() / KGetTimeStampTicksPerMs(); -#endif - - // Update the time stamp counter synchronization value. - extern volatile uint64_t timeStampCounterSynchronizationValue; - timeStampCounterSynchronizationValue = ((timeStampCounterSynchronizationValue & 0x8000000000000000) - ^ 0x8000000000000000) | ProcessorReadTimeStamp(); } InterruptContext *newContext = newThread->interruptContext; MMSpace *addressSpace = newThread->temporaryAddressSpace ?: newThread->process->vmm; MMSpaceOpenReference(addressSpace); - DoContextSwitch(newContext, VIRTUAL_ADDRESS_SPACE_IDENTIFIER(addressSpace), newThread->kernelStack, newThread, oldAddressSpace); + ArchSwitchContext(newContext, &addressSpace->data, newThread->kernelStack, newThread, oldAddressSpace); KernelPanic("Scheduler::Yield - DoContextSwitch unexpectedly returned.\n"); } diff --git a/kernel/syscall.cpp b/kernel/syscall.cpp index 4f602ac..f933994 100644 --- a/kernel/syscall.cpp +++ b/kernel/syscall.cpp @@ -9,9 +9,7 @@ KMutex eventForwardMutex; uintptr_t DoSyscall(EsSyscallType index, uintptr_t argument0, uintptr_t argument1, uintptr_t argument2, uintptr_t argument3, - uint64_t flags, bool *fatal, uintptr_t *userStackPointer); - -#define DO_SYSCALL_BATCHED (2) + bool batched, bool *fatal, uintptr_t *userStackPointer); struct MessageQueue { bool SendMessage(void *target, EsMessage *message); // Returns false if the message queue is full. @@ -1244,7 +1242,7 @@ SYSCALL_IMPLEMENT(ES_SYSCALL_THREAD_STACK_SIZE) { KMutexAcquire(¤tVMM->reserveMutex); if (thread->userStackCommit <= argument3 && argument3 <= thread->userStackReserve && !(argument3 & (K_PAGE_BITS - 1)) && region) { -#ifdef K_STACK_GROWS_DOWN +#ifdef K_ARCH_STACK_GROWS_DOWN success = MMCommitRange(currentVMM, region, (thread->userStackReserve - argument3) / K_PAGE_SIZE, argument3 / K_PAGE_SIZE); #else success = MMCommitRange(currentVMM, region, 0, argument3 / K_PAGE_SIZE); @@ -1293,7 +1291,7 @@ SYSCALL_IMPLEMENT(ES_SYSCALL_BATCH) { EsBatchCall call = calls[i]; bool fatal = false; uintptr_t _returnValue = calls[i].returnValue = DoSyscall(call.index, call.argument0, call.argument1, call.argument2, call.argument3, - DO_SYSCALL_BATCHED, &fatal, userStackPointer); + true /* batched */, &fatal, userStackPointer); if (fatal) SYSCALL_RETURN(_returnValue, true); if (calls[i].stopBatchIfError && ES_CHECK_ERROR(_returnValue)) break; if (currentThread->terminating) break; @@ -1928,12 +1926,8 @@ SyscallFunction syscallFunctions[ES_SYSCALL_COUNT + 1] { #pragma GCC diagnostic pop -uintptr_t DoSyscall(EsSyscallType index, - uintptr_t argument0, uintptr_t argument1, - uintptr_t argument2, uintptr_t argument3, - uint64_t flags, bool *fatal, uintptr_t *userStackPointer) { - bool batched = flags & DO_SYSCALL_BATCHED; - +uintptr_t DoSyscall(EsSyscallType index, uintptr_t argument0, uintptr_t argument1, uintptr_t argument2, uintptr_t argument3, + bool batched, bool *fatal, uintptr_t *userStackPointer) { // Interrupts need to be enabled during system calls, // because many of them block on mutexes or events. ProcessorEnableInterrupts(); diff --git a/kernel/terminal.cpp b/kernel/terminal.cpp index 325fe78..252eb9f 100644 --- a/kernel/terminal.cpp +++ b/kernel/terminal.cpp @@ -4,7 +4,6 @@ #ifdef IMPLEMENTATION #include -#include "x86_64.h" #define TERMINAL_ADDRESS ((uint16_t *) (LOW_MEMORY_MAP_START + 0xB8000)) @@ -17,6 +16,8 @@ KMutex printLock; #endif void DebugWriteCharacter(uintptr_t character); +extern "C" void ProcessorDebugOutputByte(uint8_t byte); +int KWaitKey(); #ifdef ARCH_X86_COMMON bool printToDebugger = false; @@ -250,7 +251,13 @@ void KernelPanic(const char *format, ...) { #ifdef POST_PANIC_DEBUGGING uintptr_t kernelLogEnd = kernelLogPosition; EsPrint("Press 'D' to enter debugger.\n"); - while (KWaitKey() != ES_SCANCODE_D); + + while (true) { + int key = KWaitKey(); + if (key == ES_SCANCODE_D) break; + if (key == -1) ProcessorHalt(); + } + graphics.debuggerActive = true; while (true) { diff --git a/kernel/x86_64.cpp b/kernel/x86_64.cpp index 29b0301..db720c7 100644 --- a/kernel/x86_64.cpp +++ b/kernel/x86_64.cpp @@ -2,24 +2,6 @@ typedef struct ACPIProcessor ArchCPU; -// Interrupt vectors: -// 0x00 - 0x1F: CPU exceptions -// 0x20 - 0x2F: PIC (disabled, spurious) -// 0x30 - 0x4F: Timers and low-priority IPIs. -// 0x50 - 0x6F: APIC (standard) -// 0x70 - 0xAF: MSI -// 0xF0 - 0xFE: High-priority IPIs -// 0xFF: APIC (spurious interrupt) - -#define TIMER_INTERRUPT (0x40) -#define YIELD_IPI (0x41) -#define IRQ_BASE (0x50) -#define CALL_FUNCTION_ON_ALL_PROCESSORS_IPI (0xF0) -#define KERNEL_PANIC_IPI (0) // NMIs ignore the interrupt vector. - -#define INTERRUPT_VECTOR_MSI_START (0x70) -#define INTERRUPT_VECTOR_MSI_COUNT (0x40) - struct InterruptContext { uint64_t cr2, ds; uint8_t fxsave[512 + 16]; @@ -30,7 +12,8 @@ struct InterruptContext { uint64_t rip, cs, flags, rsp, ss; }; -struct VirtualAddressSpaceData { +struct MMArchVAS { + // NOTE Must be first in the structure. See ProcessorSetAddressSpace and ArchSwitchContext. uintptr_t cr3; // Each process has a 47-bit address space. @@ -57,9 +40,6 @@ struct VirtualAddressSpaceData { KMutex mutex; // Acquire to modify the page tables. }; -#define VIRTUAL_ADDRESS_SPACE_DATA() VirtualAddressSpaceData data -#define VIRTUAL_ADDRESS_SPACE_IDENTIFIER(x) ((x)->data.cr3) - #define MM_CORE_SPACE_START (0xFFFF800100000000) #define MM_CORE_SPACE_SIZE (0xFFFF8001F0000000 - 0xFFFF800100000000) #define MM_CORE_REGIONS_START (0xFFFF8001F0000000) @@ -71,11 +51,12 @@ struct VirtualAddressSpaceData { #define MM_USER_SPACE_START (0x100000000000) #define MM_USER_SPACE_SIZE (0xF00000000000 - 0x100000000000) +#define ArchCheckBundleHeader() (header.mapAddress > 0x800000000000UL || header.mapAddress < 0x1000 || fileSize > 0x1000000000000UL) +#define ArchCheckELFHeader() (header->virtualAddress > 0x800000000000UL || header->virtualAddress < 0x1000 || header->segmentSize > 0x1000000000000UL) #define ArchIsAddressInKernelSpace(x) ((uintptr_t) (x) >= 0xFFFF800000000000) -uint8_t coreL1Commit[(0xFFFF800200000000 - 0xFFFF800100000000) >> (/* ENTRIES_PER_PAGE_TABLE_BITS */ 9 + K_PAGE_BITS + 3)]; - -uint8_t pciIRQLines[0x100 /* slots */][4 /* pins */]; +#define K_ARCH_STACK_GROWS_DOWN +#define K_ARCH_NAME "x86_64" #endif @@ -94,19 +75,19 @@ struct IRQHandler { const char *cOwnerName; }; +uint8_t pciIRQLines[0x100 /* slots */][4 /* pins */]; + MSIHandler msiHandlers[INTERRUPT_VECTOR_MSI_COUNT]; IRQHandler irqHandlers[0x40]; KSpinlock irqHandlersLock; // Also for msiHandlers. -extern uintptr_t bootloaderInformationOffset; -extern "C" bool simdSSE3Support; -extern "C" bool simdSSSE3Support; +KSpinlock ipiLock; + +uint8_t coreL1Commit[(0xFFFF800200000000 - 0xFFFF800100000000) >> (/* ENTRIES_PER_PAGE_TABLE_BITS */ 9 + K_PAGE_BITS + 3)]; volatile uintptr_t tlbShootdownVirtualAddress; volatile size_t tlbShootdownPageCount; -extern "C" uintptr_t _KThreadTerminate; - typedef void (*CallFunctionOnAllProcessorsCallbackFunction)(); volatile CallFunctionOnAllProcessorsCallbackFunction callFunctionOnAllProcessorsCallback; volatile uintptr_t callFunctionOnAllProcessorsRemaining; @@ -119,10 +100,14 @@ volatile uintptr_t callFunctionOnAllProcessorsRemaining; #define ENTRIES_PER_PAGE_TABLE (512) #define ENTRIES_PER_PAGE_TABLE_BITS (9) +void ArchSetPCIIRQLine(uint8_t slot, uint8_t pin, uint8_t line) { + pciIRQLines[slot][pin] = line; +} + bool MMArchCommitPageTables(MMSpace *space, MMRegion *region) { KMutexAssertLocked(&space->reserveMutex); - VirtualAddressSpaceData *data = &space->data; + MMArchVAS *data = &space->data; uintptr_t base = (region->baseAddress - (space == coreMMSpace ? MM_CORE_SPACE_START : 0)) & 0x7FFFFFFFF000; uintptr_t end = base + (region->pageCount << K_PAGE_BITS); @@ -589,13 +574,7 @@ bool MMArchInitialiseUserSpace(MMSpace *space) { return true; } -void ArchCleanupVirtualAddressSpace(void *argument) { - KernelLog(LOG_VERBOSE, "Arch", "remove virtual address space page", "Removing virtual address space page %x...\n", argument); - MMPhysicalFree((uintptr_t) argument); - MMDecommit(K_PAGE_SIZE, true); -} - -void MMFreeVAS(MMSpace *space) { +void MMArchFreeVAS(MMSpace *space) { for (uintptr_t i = 0; i < 256; i++) { if (!PAGE_TABLE_L4[i]) continue; @@ -617,7 +596,7 @@ void MMFreeVAS(MMSpace *space) { } if (space->data.pageTablesActive) { - KernelPanic("MMFreeVAS - Space %x still has %d page tables active.\n", space, space->data.pageTablesActive); + KernelPanic("MMArchFreeVAS - Space %x still has %d page tables active.\n", space, space->data.pageTablesActive); } KMutexAcquire(&coreMMSpace->reserveMutex); @@ -628,32 +607,16 @@ void MMFreeVAS(MMSpace *space) { MMDecommit(space->data.pageTablesCommitted * K_PAGE_SIZE, true); } -void MMFinalizeVAS(MMSpace *space) { +void MMArchFinalizeVAS(MMSpace *space) { if (!space->data.cr3) return; // Freeing the L4 page table has to be done in the kernel process, since it's the page CR3 would points to! // Therefore, this function only is called in an async task. - if (space->data.cr3 == ProcessorReadCR3()) KernelPanic("MMFinalizeVAS - Space %x is active.\n", space); + if (space->data.cr3 == ProcessorReadCR3()) KernelPanic("MMArchFinalizeVAS - Space %x is active.\n", space); PMZero(&space->data.cr3, 1, true); // Fail as fast as possible if someone's still using this page. MMPhysicalFree(space->data.cr3); MMDecommit(K_PAGE_SIZE, true); } -void ArchCheckAddressInRange(int type, uintptr_t address) { - if (type == 1) { - if ((uintptr_t) address < 0xFFFF900000000000) { - KernelPanic("ArchCheckAddressInRange - Address out of expected range.\n"); - } - } else if (type == 2) { - if ((uintptr_t) address < 0xFFFF8F8000000000 || (uintptr_t) address >= 0xFFFF900000000000) { - KernelPanic("ArchCheckAddressInRange - Address out of expected range.\n"); - } - } else { - if ((uintptr_t) address >= 0xFFFF800000000000) { - KernelPanic("ArchCheckAddressInRange - Address out of expected range.\n"); - } - } -} - uint64_t ArchGetTimeFromPITMs() { // TODO This isn't working on real hardware, but ArchDelay1Ms is? @@ -884,6 +847,14 @@ size_t ProcessorSendIPI(uintptr_t interrupt, bool nmi, int processorID) { return ignored; } +void ProcessorSendYieldIPI(Thread *thread) { + thread->receivedYieldIPI = false; + KSpinlockAcquire(&ipiLock); + ProcessorSendIPI(YIELD_IPI, false); + KSpinlockRelease(&ipiLock); + while (!thread->receivedYieldIPI); // Spin until the thread gets the IPI. +} + void ArchNextTimer(size_t ms) { while (!scheduler.started); // Wait until the scheduler is ready. GetLocalStorage()->schedulerReady = true; // Make sure this CPU can be scheduled. @@ -901,7 +872,7 @@ NewProcessorStorage AllocateNewProcessorStorage(ACPIProcessor *archCPU) { return storage; } -extern "C" void SetupProcessor2(NewProcessorStorage *storage) { +void SetupProcessor2(NewProcessorStorage *storage) { // Setup the local interrupts for the current processor. for (uintptr_t i = 0; i < acpi.lapicNMICount; i++) { @@ -1299,10 +1270,6 @@ extern "C" uintptr_t Syscall(uintptr_t argument0, uintptr_t argument1, uintptr_t return DoSyscall((EsSyscallType) argument0, argument1, argument2, argument3, argument4, false, nullptr, userStackPointer); } -bool HasSSSE3Support() { - return simdSSSE3Support; -} - uintptr_t GetBootloaderInformationOffset() { return bootloaderInformationOffset; } @@ -1333,4 +1300,16 @@ void KPCIWriteConfig(uint8_t bus, uint8_t device, uint8_t function, uint8_t offs else KernelPanic("PCIController::WriteConfig - Invalid size %d.\n", size); } +EsError ArchApplyRelocation(uintptr_t type, uint8_t *buffer, uintptr_t offset, uintptr_t result) { + if (type == 0) {} + else if (type == 10 /* R_X86_64_32 */) *((uint32_t *) (buffer + offset)) = result; + else if (type == 11 /* R_X86_64_32S */) *((uint32_t *) (buffer + offset)) = result; + else if (type == 1 /* R_X86_64_64 */) *((uint64_t *) (buffer + offset)) = result; + else if (type == 2 /* R_X86_64_PC32 */) *((uint32_t *) (buffer + offset)) = result - ((uint64_t) buffer + offset); + else if (type == 24 /* R_X86_64_PC64 */) *((uint64_t *) (buffer + offset)) = result - ((uint64_t) buffer + offset); + else if (type == 4 /* R_X86_64_PLT32 */) *((uint32_t *) (buffer + offset)) = result - ((uint64_t) buffer + offset); + else return ES_ERROR_UNSUPPORTED_FEATURE; + return ES_SUCCESS; +} + #endif diff --git a/kernel/x86_64.h b/kernel/x86_64.h index 382d472..012225a 100644 --- a/kernel/x86_64.h +++ b/kernel/x86_64.h @@ -46,21 +46,52 @@ #define IO_PCI_CONFIG (0x0CF8) #define IO_PCI_DATA (0x0CFC) +// --------------------------------- Interrupt vectors. + +// Interrupt vectors: +// 0x00 - 0x1F: CPU exceptions +// 0x20 - 0x2F: PIC (disabled, spurious) +// 0x30 - 0x4F: Timers and low-priority IPIs. +// 0x50 - 0x6F: APIC (standard) +// 0x70 - 0xAF: MSI +// 0xF0 - 0xFE: High-priority IPIs +// 0xFF: APIC (spurious interrupt) + +#define TIMER_INTERRUPT (0x40) +#define YIELD_IPI (0x41) +#define IRQ_BASE (0x50) +#define CALL_FUNCTION_ON_ALL_PROCESSORS_IPI (0xF0) +#define KERNEL_PANIC_IPI (0) // NMIs ignore the interrupt vector. + +#define INTERRUPT_VECTOR_MSI_START (0x70) +#define INTERRUPT_VECTOR_MSI_COUNT (0x40) + // --------------------------------- Forward declarations. -extern "C" uint64_t ProcessorReadCR3(); extern "C" void gdt_data(); +extern "C" void processorGDTR(); + +extern "C" uint64_t ProcessorReadCR3(); +extern "C" uintptr_t ProcessorGetRSP(); +extern "C" uintptr_t ProcessorGetRBP(); +extern "C" uint64_t ProcessorReadMXCSR(); +extern "C" void ProcessorInstallTSS(uint32_t *gdt, uint32_t *tss); +extern "C" void ProcessorAPStartup(); extern "C" void SSSE3Framebuffer32To24Copy(volatile uint8_t *destination, volatile uint8_t *source, size_t pixelGroups); +extern "C" uintptr_t _KThreadTerminate; extern bool pagingNXESupport; extern bool pagingPCIDSupport; extern bool pagingSMEPSupport; extern bool pagingTCESupport; -extern "C" void processorGDTR(); -extern "C" void SetupProcessor2(struct NewProcessorStorage *); -extern "C" void ProcessorInstallTSS(uint32_t *gdt, uint32_t *tss); +extern volatile uint64_t timeStampCounterSynchronizationValue; + +extern "C" bool simdSSE3Support; +extern "C" bool simdSSSE3Support; + +extern uintptr_t bootloaderInformationOffset; struct NewProcessorStorage { struct CPULocalStorage *local; @@ -68,11 +99,13 @@ struct NewProcessorStorage { }; NewProcessorStorage AllocateNewProcessorStorage(struct ACPIProcessor *archCPU); -bool HasSSSE3Support(); +extern "C" void SetupProcessor2(struct NewProcessorStorage *); uintptr_t GetBootloaderInformationOffset(); void ArchDelay1Ms(); // Spin for approximately 1ms. Use only during initialisation. Not thread-safe. uint64_t ArchGetTimeFromPITMs(); void *ACPIGetRSDP(); 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. +void ArchSetPCIIRQLine(uint8_t slot, uint8_t pin, uint8_t line); #endif diff --git a/kernel/x86_64.s b/kernel/x86_64.s index d7b4031..9460722 100644 --- a/kernel/x86_64.s +++ b/kernel/x86_64.s @@ -12,7 +12,6 @@ idt_data: resb idt_size %define cpu_local_storage_size 8192 ; Array of pointers to the CPU local states -[global cpu_local_storage] cpu_local_storage: resb cpu_local_storage_size [section .data] @@ -581,7 +580,6 @@ ProcessorInvalidateAllPages: mov cr4,rax ret -[global ProcessorIdle] ProcessorIdle: sti hlt @@ -773,6 +771,7 @@ ReturnFromInterruptHandler: [global ProcessorSetAddressSpace] ProcessorSetAddressSpace: + mov rdi,[rdi] mov rax,cr3 cmp rax,rdi je .cont @@ -780,11 +779,6 @@ ProcessorSetAddressSpace: .cont: ret -[global ProcessorGetAddressSpace] -ProcessorGetAddressSpace: - mov rax,cr3 - ret - [global ProcessorGetRSP] ProcessorGetRSP: mov rax,rsp @@ -796,11 +790,12 @@ ProcessorGetRBP: ret [extern PostContextSwitch] -[global DoContextSwitch] -DoContextSwitch: +[global ArchSwitchContext] +ArchSwitchContext: cli mov [gs:16],rcx mov [gs:8],rdx + mov rsi,[rsi] mov rax,cr3 cmp rax,rsi je .cont @@ -811,38 +806,11 @@ DoContextSwitch: call PostContextSwitch jmp ReturnFromInterruptHandler -[global ProcessorMagicBreakpoint] -ProcessorMagicBreakpoint: - xchg bx,bx -[global ProcessorBreakpointHelper] -ProcessorBreakpointHelper: - ret - [global ProcessorReadCR3] ProcessorReadCR3: mov rax,cr3 ret -[global ArchSpeakerBeep] -ArchSpeakerBeep: - ; Beep!!! - mov rdi,0x43 - mov rsi,0xB6 - call ProcessorOut8 - mov rdi,0x42 - mov rsi,0x97 - call ProcessorOut8 - mov rdi,0x42 - mov rsi,0x0A - call ProcessorOut8 - mov rdi,0x61 - call ProcessorIn8 - mov rsi,rax - or rsi,3 - mov rdi,0x61 - call ProcessorOut8 - ret - [global ProcessorDebugOutputByte] ProcessorDebugOutputByte: %ifdef COM_OUTPUT @@ -1083,11 +1051,3 @@ CALL_REGISTER_INDIRECT r12 CALL_REGISTER_INDIRECT r13 CALL_REGISTER_INDIRECT r14 CALL_REGISTER_INDIRECT r15 - -[global __cyg_profile_func_enter] -__cyg_profile_func_enter: - ret - -[global __cyg_profile_func_exit] -__cyg_profile_func_exit: - ret