44#define HPET_CAP_COUNTER_CLK_PERIOD_SHIFT 32
49#define HPET_CONF_ENABLE_CNF_BIT (1 << 0)
54#define HPET_CONF_LEG_RT_CNF_BIT (1 << 1)
59#define HPET_ADDRESS_SPACE_MEMORY 0
64#define HPET_ADDRESS_SPACE_IO 1
69#define HPET_FEMTOSECONDS_PER_SECOND 1000000000000000ULL
176 LOG_INFO(
"HPET overflow thread started, sleep interval %lluns\n", sleepInterval);
209 LOG_ERR(
"failed to locate HPET table\n");
232 LOG_ERR(
"HPET reported an invalid counter period %llu fs\n",
period);
245 LOG_ERR(
"failed to register HPET as system time source\n");
252 LOG_ERR(
"failed to create HPET overflow thread\n");
286 panic(
NULL,
"Failed to initialize HPET module");
299MODULE_INFO(
"HPET Driver",
"Kai Norberg",
"A High Precision Event Timer driver", OS_VERSION,
"MIT",
"PNP0103");
#define PACKED
GCC packed attribute.
NORETURN void panic(const interrupt_frame_t *frame, const char *format,...)
Panic the kernel, printing a message and halting.
#define LOG_ERR(format,...)
#define LOG_INFO(format,...)
#define PML_LOWER_TO_HIGHER(addr)
Converts an address from the lower half to the higher half.
void * vmm_map(space_t *space, void *virtAddr, void *physAddr, uint64_t length, pml_flags_t flags, space_callback_func_t func, void *private)
Maps physical memory to virtual memory in a given address space.
#define MODULE_INFO(_name, _author, _description, _version, _licence, _deviceTypes)
Macro to define module information.
@ MODULE_EVENT_DEVICE_ATTACH
@ MODULE_EVENT_DEVICE_DETACH
process_t * process_get_kernel(void)
Gets the kernel process.
bool process_has_thread(process_t *process, tid_t tid)
Checks if a process has a thread with the specified thread ID.
uint64_t clock_source_register(const clock_source_t *source)
Register a system timer source.
void clock_source_unregister(const clock_source_t *source)
Unregister a system timer source.
tid_t thread_kernel_create(thread_kernel_entry_t entry, void *arg)
Creates a new thread that runs in kernel mode and submits it to the scheduler.
uint64_t wait_unblock(wait_queue_t *queue, uint64_t amount, errno_t err)
Unblock threads waiting on a wait queue.
#define WAIT_ALL
Used to indicate that the wait should unblock all waiting threads.
#define WAIT_BLOCK_TIMEOUT(queue, condition, timeout)
Blocks until the condition is true, condition will be tested on every wakeup. Reaching the timeout wi...
#define WAIT_QUEUE_CREATE(name)
Create a wait queue initializer.
void sched_yield(void)
Yield the current thread's time slice to allow other threads to run.
static uint64_t seqlock_read_begin(seqlock_t *seqlock)
Begins a read operation on a sequence lock.
static void seqlock_write_release(seqlock_t *seqlock)
Releases the write lock of a sequence lock.
static bool seqlock_read_retry(seqlock_t *seqlock, uint64_t seq)
Checks if a read operation on a sequence lock needs to be retried.
#define SEQLOCK_CREATE()
Create a sequence lock initializer.
static void seqlock_write_acquire(seqlock_t *seqlock)
Acquires the write lock of a sequence lock.
#define PAGE_SIZE
The size of a memory page in bytes.
#define NULL
Pointer error value.
#define ERR
Integer error value.
__UINT64_TYPE__ tid_t
Thread Identifier.
__UINT64_TYPE__ clock_t
A nanosecond time.
sdt_header_t * acpi_tables_lookup(const char *signature, uint64_t minSize, uint64_t n)
Lookup the n'th table matching the signature.
static uint64_t hpet_init(void)
Initialize the HPET.
static clock_t hpet_read_ns_counter(void)
Safely read the HPET counter value in nanoseconds.
#define HPET_CONF_ENABLE_CNF_BIT
The bit to set to enable the HPET in the configuration register.
static atomic_uint64_t counter
Accumulated nanosecond counter, used to avoid overflows.
static uint64_t period
Main counter tick period in femtoseconds (10^-15 s).
static void hpet_write(hpet_register_t reg, uint64_t value)
Write to an HPET register.
hpet_register_t
HPET register offsets.
static hpet_t * hpet
Pointer to the HPET ACPI table.
static wait_queue_t overflowQueue
Wait queue for the overflow thread.
#define HPET_FEMTOSECONDS_PER_SECOND
The number of femtoseconds in one second.
#define HPET_CAP_COUNTER_CLK_PERIOD_SHIFT
The bit offset of the clock period in the capabilities register.
static atomic_bool overflowShouldStop
Flag to signal the overflow thread to stop.
static clock_t hpet_ns_per_tick(void)
Get the HPET clock period in nanoseconds.
static void hpet_overflow_thread(void *arg)
Thread function that periodically accumulates the HPET counter to prevent overflow.
static void hpet_reset_counter(void)
Reset the HPET main counter to zero and enable the HPET.
static clock_source_t source
Structure to describe the HPET to the sys time subsystem.
static void hpet_deinit(void)
Deinitialize the HPET.
static tid_t overflowThreadTid
Thread ID of the overflow thread.
static uint64_t hpet_read(hpet_register_t reg)
Read from an HPET register.
static seqlock_t counterLock
Seqlock for the accumulated counter.
static uintptr_t address
Mapped virtual address of the HPET registers.
#define HPET_ADDRESS_SPACE_MEMORY
If hpet_t::addressSpaceId is equal to this, the address is in system memory space.
@ HPET_REG_GENERAL_CONFIG
@ HPET_REG_GENERAL_CAPABILITIES_ID
@ HPET_REG_MAIN_COUNTER_VALUE
@ HPET_REG_GENERAL_INTERRUPT
@ HPET_REG_TIMER0_COMPARATOR
@ HPET_REG_TIMER0_CONFIG_CAP
uint64_t _module_procedure(const module_event_t *event)
#define atomic_store(object, desired)
#define atomic_load(object)
#define ATOMIC_VAR_INIT(value)
#define atomic_fetch_add(object, operand)
__UINTPTR_TYPE__ uintptr_t
High Precision Event Timer structure.
uint8_t legacyReplacementCapable
uint8_t registerBitOffset
The primitive that threads block on.
_PUBLIC time_t time(time_t *timer)
#define WRITE_64(address, value)