Skip to content

Commit 48f2818

Browse files
committed
Add HPET to recalibrate clock & nano time
1 parent d98f682 commit 48f2818

File tree

21 files changed

+357
-112
lines changed

21 files changed

+357
-112
lines changed

kernel/src/kernel/calls/syscall.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,7 @@ void syscallRegisterAll()
109109
_syscallRegister(G_SYSCALL_GET_TASK_FOR_IDENTIFIER, (g_syscall_handler) syscallGetTaskForIdentifier);
110110
_syscallRegister(G_SYSCALL_GET_MILLISECONDS, (g_syscall_handler) syscallGetMilliseconds);
111111
_syscallRegister(G_SYSCALL_DUMP, (g_syscall_handler) syscallDump);
112+
_syscallRegister(G_SYSCALL_GET_NANOSECONDS, (g_syscall_handler) syscallGetNanoseconds);
112113

113114
// Memory
114115
_syscallRegister(G_SYSCALL_LOWER_MEMORY_ALLOCATE, (g_syscall_handler) syscallLowerMemoryAllocate, true);

kernel/src/kernel/calls/syscall_kernquery.cpp

Lines changed: 27 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -28,60 +28,65 @@ void syscallKernQuery(g_task* task, g_syscall_kernquery* data)
2828
{
2929
if(data->command == G_KERNQUERY_TASK_LIST)
3030
{
31-
g_kernquery_task_list_data* kdata = (g_kernquery_task_list_data*) data->buffer;
31+
auto out = (g_kernquery_task_list_data*) data->buffer;
3232

33-
uint32_t rem = kdata->id_buffer_size;
34-
kdata->filled_ids = 0;
33+
uint32_t rem = out->id_buffer_size;
34+
out->filled_ids = 0;
3535
auto iter = hashmapIteratorStart(taskGlobalMap);
3636
while(rem-- && hashmapIteratorHasNext(&iter))
3737
{
3838
auto next = hashmapIteratorNext(&iter)->value;
39-
kdata->id_buffer[kdata->filled_ids++] = next->id;
39+
out->id_buffer[out->filled_ids++] = next->id;
4040
}
4141
data->status = G_KERNQUERY_STATUS_SUCCESSFUL;
4242
hashmapIteratorEnd(&iter);
4343
}
4444
else if(data->command == G_KERNQUERY_TASK_COUNT)
4545
{
46-
g_kernquery_task_count_data* kdata = (g_kernquery_task_count_data*) data->buffer;
46+
auto out = (g_kernquery_task_count_data*) data->buffer;
4747

4848
data->status = G_KERNQUERY_STATUS_SUCCESSFUL;
49-
kdata->count = hashmapSize(taskGlobalMap);
49+
out->count = hashmapSize(taskGlobalMap);
5050
}
5151
else if(data->command == G_KERNQUERY_TASK_GET_BY_ID)
5252
{
53-
g_kernquery_task_get_data* kdata = (g_kernquery_task_get_data*) data->buffer;
53+
auto out = (g_kernquery_task_get_data*) data->buffer;
5454

55-
g_task* ktask = taskingGetById(kdata->id);
56-
if(!ktask || ktask->status == G_TASK_STATUS_DEAD)
55+
g_task* target = taskingGetById(out->id);
56+
mutexAcquire(&target->lock);
57+
58+
if(!target || target->status == G_TASK_STATUS_DEAD)
5759
{
5860
data->status = G_KERNQUERY_STATUS_UNKNOWN_ID;
59-
kdata->id = -1;
61+
out->id = -1;
6062
}
6163
else
6264
{
6365
data->status = G_KERNQUERY_STATUS_SUCCESSFUL;
64-
kdata->found = true;
65-
kdata->id = ktask->id;
66-
kdata->parent = ktask->process->id;
67-
kdata->type = ktask->type;
66+
out->found = true;
67+
out->id = target->id;
68+
out->parent = target->process->id;
69+
out->type = target->type;
6870

69-
if(ktask->process->environment.executablePath)
70-
stringCopy(kdata->source_path, ktask->process->environment.executablePath);
71+
if(target->process->environment.executablePath)
72+
stringCopy(out->source_path, target->process->environment.executablePath);
7173
else
72-
kdata->source_path[0] = 0;
74+
out->source_path[0] = 0;
7375

74-
const char* identifier = taskingDirectoryGetIdentifier(ktask->id);
76+
const char* identifier = taskingDirectoryGetIdentifier(target->id);
7577
if(identifier)
76-
stringCopy(kdata->identifier, identifier);
78+
stringCopy(out->identifier, identifier);
7779
else
78-
kdata->identifier[0] = 0;
80+
out->identifier[0] = 0;
7981

80-
kdata->memory_used = 0; // TODO
82+
out->cpu_time = target->statistics.timesScheduled;
83+
out->memory_used = 0; // TODO
8184
}
85+
86+
mutexRelease(&target->lock);
8287
}
8388
else
8489
{
8590
data->status = G_KERNQUERY_STATUS_ERROR;
8691
}
87-
}
92+
}

kernel/src/kernel/calls/syscall_tasking.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
#include "kernel/tasking/scheduler/scheduler.hpp"
2727
#include "kernel/tasking/tasking_directory.hpp"
2828
#include "kernel/tasking/clock.hpp"
29+
#include "kernel/system/timing/hpet.hpp"
2930
#include "kernel/utils/wait_queue.hpp"
3031
#include "shared/logger/logger.hpp"
3132
#include "shared/utils/string.hpp"
@@ -199,6 +200,14 @@ void syscallGetMilliseconds(g_task* task, g_syscall_millis* data)
199200
data->millis = clockGetLocal()->time;
200201
}
201202

203+
void syscallGetNanoseconds(g_task* task, g_syscall_nanos* data)
204+
{
205+
if(hpetIsAvailable())
206+
data->nanos = hpetGetNanos();
207+
else
208+
data->nanos = clockGetLocal()->time * 1000000LL;
209+
}
210+
202211
void syscallGetExecutablePath(g_task* task, g_syscall_get_executable_path* data)
203212
{
204213
if(task->process->environment.executablePath)

kernel/src/kernel/calls/syscall_tasking.hpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,8 @@ void syscallReleaseCliArguments(g_task* task, g_syscall_cli_args_release* data);
6060

6161
void syscallGetMilliseconds(g_task* task, g_syscall_millis* data);
6262

63+
void syscallGetNanoseconds(g_task* task, g_syscall_nanos* data);
64+
6365
void syscallGetExecutablePath(g_task* task, g_syscall_get_executable_path* data);
6466

6567
void syscallGetWorkingDirectory(g_task* task, g_syscall_get_working_directory* data);

kernel/src/kernel/ipc/pipes.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ g_fs_pipe_status pipeCreate(g_fs_phys_id* outPipeId)
4242

4343
mutexInitializeTask(&pipe->lock, __func__);
4444
pipe->capacity = G_PIPE_DEFAULT_CAPACITY;
45-
pipe->buffer = (uint8_t*) memoryAllocateKernelRange(G_PAGE_ALIGN_UP(pipe->capacity) / G_PAGE_SIZE);
45+
pipe->buffer = (uint8_t*) memoryAllocateKernel(G_PAGE_ALIGN_UP(pipe->capacity) / G_PAGE_SIZE);
4646
pipe->readPosition = pipe->buffer;
4747
pipe->writePosition = pipe->buffer;
4848
waitQueueInitialize(&pipe->waitersRead);

kernel/src/kernel/memory/memory.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ void memoryPhysicalFree(g_physical_address page)
8484
bitmapPageAllocatorMarkFree(&memoryPhysicalAllocator, page);
8585
}
8686

87-
g_virtual_address memoryAllocateKernelRange(int32_t pages)
87+
g_virtual_address memoryAllocateKernel(int32_t pages)
8888
{
8989
g_virtual_address virt = addressRangePoolAllocate(memoryVirtualRangePool, pages);
9090
for(int32_t i = 0; i < pages; i++)

kernel/src/kernel/memory/memory.hpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ void memoryPhysicalFree(g_physical_address page);
4949
/**
5050
* Allocates and maps a memory range with the given number of pages.
5151
*/
52-
g_virtual_address memoryAllocateKernelRange(int32_t pages);
52+
g_virtual_address memoryAllocateKernel(int32_t pages);
5353

5454
/**
5555
* Frees a memory range allocated with <memoryAllocateKernelRange>.
@@ -59,7 +59,8 @@ void memoryFreeKernelRange(g_virtual_address address);
5959
/**
6060
* Creates an on-demand mapping for a file in memory.
6161
*/
62-
void memoryOnDemandMapFile(g_process* process, g_fd file, g_offset fileOffset, g_address fileStart, g_ptrsize fileSize, g_ptrsize memorySize);
62+
void memoryOnDemandMapFile(g_process* process, g_fd file, g_offset fileOffset, g_address fileStart, g_ptrsize fileSize,
63+
g_ptrsize memorySize);
6364

6465
/**
6566
* Searches for an on-demand mapping containing the given address.

kernel/src/kernel/system/acpi/acpi.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ g_acpi_entry* acpiGetEntryWithSignature(const char* signature)
4141
}
4242
cur = cur->next;
4343
}
44-
return 0;
44+
return nullptr;
4545
}
4646

4747
void acpiInitialize()

kernel/src/kernel/system/acpi/acpi.hpp

Lines changed: 31 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -28,27 +28,46 @@
2828
// Set a maximum for SDTs to avoid problems with possible junk tables
2929
#define G_SDT_MAXIMUM_BYTES 0x10000
3030

31+
/**
32+
* Header of an ACPI table
33+
*/
3134
struct g_acpi_table_header
3235
{
33-
uint8_t signature[4];
34-
uint32_t length;
35-
uint8_t revision;
36-
uint8_t checksum;
37-
uint8_t oemId[6];
38-
uint8_t oemTableId[8];
39-
uint32_t oemRevision;
40-
uint32_t creatorId;
41-
uint32_t creatorRevision;
36+
uint8_t signature[4];
37+
uint32_t length;
38+
uint8_t revision;
39+
uint8_t checksum;
40+
uint8_t oemId[6];
41+
uint8_t oemTableId[8];
42+
uint32_t oemRevision;
43+
uint32_t creatorId;
44+
uint32_t creatorRevision;
4245
}__attribute__((packed));
4346

47+
48+
/**
49+
* Generic address structure
50+
*/
51+
struct g_acpi_gas
52+
{
53+
uint8_t addressSpace;
54+
uint8_t bitWidth;
55+
uint8_t bitOffset;
56+
uint8_t accessSize;
57+
uint64_t address;
58+
}__attribute__((packed));
59+
60+
/**
61+
* Internal listing structure
62+
*/
4463
struct g_acpi_entry
4564
{
46-
g_acpi_table_header* header;
47-
g_acpi_entry* next;
65+
g_acpi_table_header* header;
66+
g_acpi_entry* next;
4867
};
4968

5069
/**
51-
*
70+
* Initializes ACPI by reading the tables
5271
*/
5372
void acpiInitialize();
5473

kernel/src/kernel/system/system.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
#include "kernel/system/acpi/acpi.hpp"
2525
#include "kernel/system/interrupts/apic/apic.hpp"
2626
#include "kernel/system/interrupts/interrupts.hpp"
27+
#include "kernel/system/timing/hpet.hpp"
2728
#include "kernel/system/smp.hpp"
2829
#include "shared/panic.hpp"
2930
#include "shared/logger/logger.hpp"
@@ -38,6 +39,7 @@ void systemInitializeBsp(g_physical_address initialPdPhys)
3839

3940
acpiInitialize();
4041
apicDetect();
42+
hpetInitialize();
4143

4244
if(!processorListAvailable())
4345
panic("%! no processors found", "system");
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
2+
* *
3+
* Ghost, a micro-kernel based operating system for the x86 architecture *
4+
* Copyright (C) 2025, Max Schlüssel <lokoxe@gmail.com> *
5+
* *
6+
* This program is free software: you can redistribute it and/or modify *
7+
* it under the terms of the GNU General Public License as published by *
8+
* the Free Software Foundation, either version 3 of the License, or *
9+
* (at your option) any later version. *
10+
* *
11+
* This program is distributed in the hope that it will be useful, *
12+
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
13+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
14+
* GNU General Public License for more details. *
15+
* *
16+
* You should have received a copy of the GNU General Public License *
17+
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
18+
* *
19+
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
20+
21+
#include "kernel/system/timing/hpet.hpp"
22+
#include "kernel/memory/memory.hpp"
23+
#include "kernel/system/acpi/acpi.hpp"
24+
#include "shared/logger/logger.hpp"
25+
26+
static volatile uint64_t* mmio = nullptr;
27+
static bool available = false;
28+
static uint64_t frequency = HPET_DEFAULT_FREQUENCY;
29+
static double periodsPerSecond = 1.0 / frequency;
30+
31+
void _hpetFindAndMap();
32+
33+
void hpetInitialize()
34+
{
35+
_hpetFindAndMap();
36+
37+
// Read correct frequency
38+
uint64_t capabilities = mmio[HPET_GEN_CAP_REG / 8];
39+
uint32_t clockPeriod = (capabilities >> 32) & 0xFFFFFFFF;
40+
frequency = (1000000000000000.0 / clockPeriod);
41+
periodsPerSecond = 1.0 / frequency;
42+
43+
// Make sure it is enabled
44+
mmio[HPET_GEN_CONFIG_REG / 8] |= 1;
45+
46+
available = true;
47+
}
48+
49+
void _hpetFindAndMap()
50+
{
51+
auto entry = acpiGetEntryWithSignature("HPET");
52+
if(!entry)
53+
{
54+
logInfo("%! not present, timing will be inaccurate", "hpet");
55+
return;
56+
}
57+
58+
auto hpet = (g_acpi_hpet*) entry->header;
59+
if(hpet->baseAddress.addressSpace != 0)
60+
{
61+
logInfo("%! only supported with MMIO", "hpet");
62+
return;
63+
}
64+
65+
auto virtBase = addressRangePoolAllocate(memoryVirtualRangePool, 1);
66+
pagingMapPage(virtBase, hpet->baseAddress.address, G_PAGE_TABLE_KERNEL_DEFAULT, G_PAGE_TABLE_KERNEL_DEFAULT,
67+
G_PAGE_KERNEL_UNCACHED);
68+
69+
mmio = (volatile uint64_t*) virtBase;
70+
}
71+
72+
bool hpetIsAvailable()
73+
{
74+
return available;
75+
}
76+
77+
uint64_t hpetGetNanos()
78+
{
79+
if(!available)
80+
return 0;
81+
82+
uint64_t counterValue = mmio[HPET_MAIN_COUNTER_REG / 8];
83+
return (uint64_t) ((double) counterValue * periodsPerSecond * 1000000000);
84+
}

0 commit comments

Comments
 (0)