Fix HPET unaligned read/writes on bochs
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
#include <amd64/hpet.h>
|
||||
#include <libk/std.h>
|
||||
#include <limine/requests.h>
|
||||
#include <sync/spin_lock.h>
|
||||
#include <sys/debug.h>
|
||||
#include <sys/mm.h>
|
||||
#include <uacpi/acpi.h>
|
||||
@@ -15,9 +16,12 @@
|
||||
static bool hpet_32bits = 1;
|
||||
static uintptr_t hpet_paddr;
|
||||
static uint64_t hpet_clock_nano;
|
||||
static spin_lock_t hpet_lock = SPIN_LOCK_INIT;
|
||||
|
||||
extern void amd64_spin (void);
|
||||
|
||||
/* These functions assume hpet_lock is held by the caller! */
|
||||
|
||||
static uint64_t amd64_hpet_read (uint32_t reg) {
|
||||
struct limine_hhdm_response* hhdm = limine_hhdm_request.response;
|
||||
uintptr_t hpet_vaddr = hpet_paddr + (uintptr_t)hhdm->offset;
|
||||
@@ -36,13 +40,27 @@ static void amd64_hpet_write (uint32_t reg, uint64_t value) {
|
||||
|
||||
static uint64_t amd64_hpet_timestamp (void) { return amd64_hpet_read (HPET_MCVR); }
|
||||
|
||||
uint64_t amd64_hpet_current_nano (void) { return amd64_hpet_timestamp () * hpet_clock_nano; }
|
||||
uint64_t amd64_hpet_current_nano (bool lock) {
|
||||
if (lock)
|
||||
spin_lock (&hpet_lock);
|
||||
|
||||
uint64_t t = amd64_hpet_timestamp () * hpet_clock_nano;
|
||||
|
||||
if (lock)
|
||||
spin_unlock (&hpet_lock);
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
void amd64_hpet_sleep_micro (uint64_t us) {
|
||||
spin_lock (&hpet_lock);
|
||||
|
||||
uint64_t start = amd64_hpet_timestamp ();
|
||||
uint64_t conv = us * 1000;
|
||||
while (((amd64_hpet_timestamp () - start) * hpet_clock_nano) < conv)
|
||||
__asm__ volatile ("pause" ::: "memory");
|
||||
|
||||
spin_unlock (&hpet_lock);
|
||||
}
|
||||
|
||||
void amd64_hpet_init (void) {
|
||||
@@ -61,7 +79,19 @@ void amd64_hpet_init (void) {
|
||||
|
||||
hpet_32bits = (amd64_hpet_read (HPET_GCIDR) & (1 << 13)) ? 0 : 1;
|
||||
|
||||
amd64_hpet_write (HPET_GCR, amd64_hpet_read (HPET_GCR) | 0x01);
|
||||
/* reset */
|
||||
amd64_hpet_write (HPET_GCR, 0);
|
||||
amd64_hpet_write (HPET_MCVR, 0);
|
||||
amd64_hpet_write (HPET_GCR, 1);
|
||||
|
||||
hpet_clock_nano = amd64_hpet_read (HPET_GCIDR + 4) / 1000000;
|
||||
uint64_t gcidr = amd64_hpet_read (HPET_GCIDR);
|
||||
if (hpet_32bits) {
|
||||
uint32_t low = (uint32_t)gcidr;
|
||||
uint32_t high = (uint32_t)amd64_hpet_read (HPET_GCIDR + 4);
|
||||
gcidr = (((uint64_t)high << 32) | low);
|
||||
}
|
||||
|
||||
uint64_t period_fs = (gcidr >> 32);
|
||||
|
||||
hpet_clock_nano = period_fs / 1000000;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user