From 2e457eb7923534b299740edb58c08f2ef0388fd2 Mon Sep 17 00:00:00 2001 From: nakst <> Date: Sat, 23 Oct 2021 21:39:02 +0100 Subject: [PATCH] hpet; minimal fonts option --- apps/test.cpp | 33 +++++++++++++++++++++ drivers/acpi.cpp | 72 +++++++++++++++++++++++++++++++++------------ kernel/kernel.h | 3 +- kernel/x86_64.cpp | 4 ++- kernel/x86_64.h | 1 + util/build.c | 32 ++++++++++++++++---- util/build_common.h | 2 ++ 7 files changed, 121 insertions(+), 26 deletions(-) diff --git a/apps/test.cpp b/apps/test.cpp index 73090c5..df6ac39 100644 --- a/apps/test.cpp +++ b/apps/test.cpp @@ -144,12 +144,45 @@ int TestCanvasMessage(EsElement *, EsMessage *message) { return 0; } +const uint16_t daysBeforeMonthStart[] = { + 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, // Normal year. + 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, // Leap year. +}; + +uint64_t DateToLinear(const EsDateComponents *components) { + uint64_t dayCount = 365 * components->year + daysBeforeMonthStart[components->month - 1] + components->day - 1; + uint16_t year = components->month < 3 ? components->year - 1 : components->year; + dayCount += 1 + year / 4 - year / 100 + year / 400; // Add additional days for leap years, only including this year's if we're past February. + return components->millisecond + 1000 * (components->second + 60 * (components->minute + 60 * (components->hour + 24 * dayCount))); +} + void InitialiseInstance(EsInstance *instance) { // EsPanel *panel = EsPanelCreate(instance->window, ES_CELL_FILL, ES_STYLE_PANEL_WINDOW_DIVIDER); // textbox = EsTextboxCreate(panel, ES_CELL_FILL | ES_TEXTBOX_ALLOW_TABS | ES_TEXTBOX_MULTILINE, ES_STYLE_TEXTBOX_NO_BORDER); // Test(); EsPanel *panel = EsPanelCreate(instance->window, ES_CELL_FILL, &stylePanel); + + EsButtonOnCommand(EsButtonCreate(panel, ES_FLAGS_DEFAULT, 0, "Timing"), [] (EsInstance *, EsElement *element, EsCommand *) { + EsDateComponents start, end; + + EsDateNowUTC(&start); + EsPerformanceTimerPush(); + + for (uintptr_t i = 0; i < 50000000; i++) { + EsHeapFree(EsHeapAllocate(10, true)); + } + + double performanceTime = EsPerformanceTimerPop(); + EsDateNowUTC(&end); + + char message[4096]; + size_t messageBytes = EsStringFormat(message, sizeof(message), "Performance time: %F s.\nScheduler time: %F s.\n", + performanceTime, (DateToLinear(&end) - DateToLinear(&start)) / 1000.0); + EsDialogShow(element->window, "Timing results", -1, + message, messageBytes, ES_ICON_DIALOG_INFORMATION, ES_DIALOG_ALERT_OK_BUTTON); + }); + EsButtonCreate(panel, ES_BUTTON_CHECKBOX, 0, "Checkbox"); EsTextboxCreate(panel); diff --git a/drivers/acpi.cpp b/drivers/acpi.cpp index 3d87b0f..73c82da 100644 --- a/drivers/acpi.cpp +++ b/drivers/acpi.cpp @@ -1,9 +1,9 @@ #define SIGNATURE_RSDP (0x2052545020445352) - #define SIGNATURE_RSDT (0x54445352) #define SIGNATURE_XSDT (0x54445358) #define SIGNATURE_MADT (0x43495041) #define SIGNATURE_FADT (0x50434146) +#define SIGNATURE_HPET (0x54455048) struct RootSystemDescriptorPointer { uint64_t signature; @@ -91,23 +91,6 @@ struct ACPILapic { size_t ticksPerMs; }; -void ACPILapic::ArchNextTimer(size_t ms) { - WriteRegister(0x320 >> 2, TIMER_INTERRUPT | (1 << 17)); - WriteRegister(0x380 >> 2, ticksPerMs * ms); -} - -void ACPILapic::EndOfInterrupt() { - WriteRegister(0xB0 >> 2, 0); -} - -uint32_t ACPILapic::ReadRegister(uint32_t reg) { - return address[reg]; -} - -void ACPILapic::WriteRegister(uint32_t reg, uint32_t value) { - address[reg] = value; -} - struct ACPI { void Initialise(); void FindRootSystemDescriptorPointer(); @@ -132,12 +115,42 @@ struct ACPI { bool ps2ControllerUnavailable, vgaControllerUnavailable; uint8_t centuryRegisterIndex; + volatile uint64_t *hpetBaseAddress; + uint64_t hpetPeriod; // 10^-15 seconds. + KDevice *computer; }; ACPI acpi; +void ACPILapic::ArchNextTimer(size_t ms) { + WriteRegister(0x320 >> 2, TIMER_INTERRUPT | (1 << 17)); + WriteRegister(0x380 >> 2, ticksPerMs * ms); +} + +void ACPILapic::EndOfInterrupt() { + WriteRegister(0xB0 >> 2, 0); +} + +uint32_t ACPILapic::ReadRegister(uint32_t reg) { + return address[reg]; +} + +void ACPILapic::WriteRegister(uint32_t reg, uint32_t value) { + address[reg] = value; +} + #ifdef ARCH_X86_COMMON +uint64_t ArchGetTimeMs() { + if (acpi.hpetBaseAddress && acpi.hpetPeriod) { + __int128 fsToMs = 1000000000000; + __int128 reading = acpi.hpetBaseAddress[30]; + return (uint64_t) (reading * (__int128) acpi.hpetPeriod / fsToMs); + } else { + return ArchGetTimeFromPITMs(); + } +} + void ACPI::FindRootSystemDescriptorPointer() { PhysicalMemoryRegion searchRegions[2]; @@ -977,6 +990,29 @@ void ACPI::Initialise() { } MMFree(kernelMMSpace, fadt); + } else if (header->signature == SIGNATURE_HPET) { + ACPIDescriptorTable *hpet = (ACPIDescriptorTable *) MMMapPhysical(kernelMMSpace, address, header->length, ES_FLAGS_DEFAULT); + hpet->Check(); + + if (header->length > 52 && ((uint8_t *) header)[52] == 0) { + uint64_t baseAddress; + EsMemoryCopy(&baseAddress, (uint8_t *) header + 44, sizeof(uint64_t)); + KernelLog(LOG_INFO, "ACPI", "HPET", "Found primary HPET with base address %x.\n", baseAddress); + hpetBaseAddress = (uint64_t *) MMMapPhysical(kernelMMSpace, baseAddress, 1024, ES_FLAGS_DEFAULT); + + if (hpetBaseAddress) { + hpetBaseAddress[2] |= 1; // Start the main counter. + + hpetPeriod = hpetBaseAddress[0] >> 32; + uint8_t revisionID = hpetBaseAddress[0] & 0xFF; + uint64_t initialCount = hpetBaseAddress[30]; + + KernelLog(LOG_INFO, "ACPI", "HPET", "HPET has period of %d fs, revision ID %d, and initial count %d.\n", + hpetPeriod, revisionID, initialCount); + } + } + + MMFree(kernelMMSpace, hpet); } MMFree(kernelMMSpace, header); diff --git a/kernel/kernel.h b/kernel/kernel.h index a03869f..8208d4a 100644 --- a/kernel/kernel.h +++ b/kernel/kernel.h @@ -15,7 +15,8 @@ #define CC_ACTIVE_SECTION_SIZE ((EsFileOffset) 262144) // Maximum number of active sections on the modified list. If exceeded, writers will wait for it to drop before retrying. -#define CC_MAX_MODIFIED (33554432 / CC_ACTIVE_SECTION_SIZE) +// TODO This should based off the amount of physical memory. +#define CC_MAX_MODIFIED (67108864 / CC_ACTIVE_SECTION_SIZE) // The size of the kernel's address space used for mapping active sections. #if defined(ARCH_32) diff --git a/kernel/x86_64.cpp b/kernel/x86_64.cpp index 923e754..5332feb 100644 --- a/kernel/x86_64.cpp +++ b/kernel/x86_64.cpp @@ -654,7 +654,9 @@ void ArchCheckAddressInRange(int type, uintptr_t address) { } } -uint64_t ArchGetTimeMs() { +uint64_t ArchGetTimeFromPITMs() { + // TODO This isn't working on real hardware, but ArchDelay1Ms is? + // NOTE This will only work if called at least once every 50 ms. // (The PIT only stores a 16-bit counter, which is depleted every 50 ms.) diff --git a/kernel/x86_64.h b/kernel/x86_64.h index 4ed4b3a..59e5e7a 100644 --- a/kernel/x86_64.h +++ b/kernel/x86_64.h @@ -27,6 +27,7 @@ NewProcessorStorage AllocateNewProcessorStorage(struct ACPIProcessor *archCPU); bool HasSSSE3Support(); uintptr_t GetBootloaderInformationOffset(); void ArchDelay1Ms(); // Spin for approximately 1ms. Use only during initialisation. Not thread-safe. +uint64_t ArchGetTimeFromPITMs(); void *ACPIGetRSDP(); uint8_t ACPIGetCenturyRegisterIndex(); diff --git a/util/build.c b/util/build.c index 1d48ebd..708c3f6 100644 --- a/util/build.c +++ b/util/build.c @@ -56,7 +56,7 @@ BuildFont fonts[] = { { "2i", "Inter Extra Light Italic.otf" }, { "3", "Inter Light.otf" }, { "3i", "Inter Light Italic.otf" }, - { "4", "Inter Regular.otf" }, + { "4", "Inter Regular.otf", .required = true }, { "4i", "Inter Regular Italic.otf" }, { "5", "Inter Medium.otf" }, { "5i", "Inter Medium Italic.otf" }, @@ -72,7 +72,7 @@ BuildFont fonts[] = { } }, { "Hack", "Hack License.md", "Mono", "Latn,Grek,Cyrl", (FontFile []) { - { "4", "Hack Regular.ttf" }, + { "4", "Hack Regular.ttf", .required = true }, { "4i", "Hack Regular Italic.ttf" }, { "7", "Hack Bold.ttf" }, { "7i", "Hack Bold Italic.ttf" }, @@ -268,19 +268,39 @@ void Compile(uint32_t flags, int partitionSize, const char *volumeLabel) { uintptr_t fontIndex = 0; + bool requiredFontsOnly = IsOptionEnabled("BuildCore.RequiredFontsOnly"); + while (fonts[fontIndex].files) { BuildFont *font = fonts + fontIndex; - fprintf(f, "[@font %s]\ncategory=%s\nscripts=%s\nlicense=%s\n", font->name, font->category, font->scripts, font->license); + fontIndex++; + uintptr_t fileIndex = 0; + bool noRequiredFiles = true; while (font->files[fileIndex].path) { - FontFile *file = font->files + fileIndex; - fprintf(f, ".%s=%s\n", file->type, file->path); + if (font->files[fileIndex].required) { + noRequiredFiles = false; + break; + } + fileIndex++; } + if (noRequiredFiles) { + continue; + } + + fprintf(f, "[@font %s]\ncategory=%s\nscripts=%s\nlicense=%s\n", font->name, font->category, font->scripts, font->license); + fileIndex = 0; + + while (font->files[fileIndex].path) { + FontFile *file = font->files + fileIndex; + fileIndex++; + if (requiredFontsOnly && !file->required) continue; + fprintf(f, ".%s=%s\n", file->type, file->path); + } + fprintf(f, "\n"); - fontIndex++; } if (~flags & COMPILE_SKIP_COMPILE) { diff --git a/util/build_common.h b/util/build_common.h index 4907a86..435965d 100644 --- a/util/build_common.h +++ b/util/build_common.h @@ -40,6 +40,7 @@ typedef struct ApplicationDependencies { typedef struct FontFile { const char *type; const char *path; + bool required; } FontFile; typedef struct BuildFont { @@ -317,6 +318,7 @@ Option options[] = { { "Emulator.SerialToFile", OPTION_TYPE_BOOL, { .b = true } }, { "BuildCore.Verbose", OPTION_TYPE_BOOL, { .b = false } }, { "BuildCore.NoImportPOSIX", OPTION_TYPE_BOOL, { .b = false } }, + { "BuildCore.RequiredFontsOnly", OPTION_TYPE_BOOL, { .b = false } }, { "General.first_application", OPTION_TYPE_STRING, { .s = NULL } }, { "General.wallpaper", OPTION_TYPE_STRING, { .s = NULL } }, { "General.installation_state", OPTION_TYPE_STRING, { .s = "0" } },