Fix HPET unaligned read/writes on bochs

This commit is contained in:
2025-12-22 21:06:48 +01:00
parent 69feceaaae
commit 849df9c27d
5 changed files with 43 additions and 12 deletions

View File

@@ -2,7 +2,7 @@ cpu: model=p4_prescott_celeron_336
memory: guest=4096 host=2048 memory: guest=4096 host=2048
romimage: file=/usr/share/bochs/BIOS-bochs-latest, options=fastboot romimage: file=/usr/share/bochs/BIOS-bochs-latest
vgaromimage: file=/usr/share/bochs/VGABIOS-lgpl-latest.bin vgaromimage: file=/usr/share/bochs/VGABIOS-lgpl-latest.bin
ata0: enabled=1 ata0: enabled=1

View File

@@ -1,3 +1,3 @@
#!/bin/sh #!/bin/sh
qemu-system-x86_64 -M q35 -m 4G -serial mon:stdio -cdrom mop3.iso qemu-system-x86_64 -M q35 -m 4G -serial mon:stdio -enable-kvm -cdrom mop3.iso

View File

@@ -23,13 +23,14 @@ void bootmain (void) {
amd64_ioapic_init (); amd64_ioapic_init ();
amd64_hpet_init (); amd64_hpet_init ();
int* a = malloc (sizeof (int)); /* int* a = malloc (sizeof (int)); */
*a = 6969; /* *a = 6969; */
DEBUG ("a=%p, *a=%d\n", a, *a); /* DEBUG ("a=%p, *a=%d\n", a, *a); */
amd64_hpet_sleep_micro (3000000); for (size_t i = 0; i < 1000; i++) {
DEBUG ("i=%zu\n", i);
DEBUG ("woke up!!!\n"); amd64_hpet_sleep_micro (1000000);
}
for (;;) for (;;)
; ;

View File

@@ -1,6 +1,7 @@
#include <amd64/hpet.h> #include <amd64/hpet.h>
#include <libk/std.h> #include <libk/std.h>
#include <limine/requests.h> #include <limine/requests.h>
#include <sync/spin_lock.h>
#include <sys/debug.h> #include <sys/debug.h>
#include <sys/mm.h> #include <sys/mm.h>
#include <uacpi/acpi.h> #include <uacpi/acpi.h>
@@ -15,9 +16,12 @@
static bool hpet_32bits = 1; static bool hpet_32bits = 1;
static uintptr_t hpet_paddr; static uintptr_t hpet_paddr;
static uint64_t hpet_clock_nano; static uint64_t hpet_clock_nano;
static spin_lock_t hpet_lock = SPIN_LOCK_INIT;
extern void amd64_spin (void); extern void amd64_spin (void);
/* These functions assume hpet_lock is held by the caller! */
static uint64_t amd64_hpet_read (uint32_t reg) { static uint64_t amd64_hpet_read (uint32_t reg) {
struct limine_hhdm_response* hhdm = limine_hhdm_request.response; struct limine_hhdm_response* hhdm = limine_hhdm_request.response;
uintptr_t hpet_vaddr = hpet_paddr + (uintptr_t)hhdm->offset; 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); } 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) { void amd64_hpet_sleep_micro (uint64_t us) {
spin_lock (&hpet_lock);
uint64_t start = amd64_hpet_timestamp (); uint64_t start = amd64_hpet_timestamp ();
uint64_t conv = us * 1000; uint64_t conv = us * 1000;
while (((amd64_hpet_timestamp () - start) * hpet_clock_nano) < conv) while (((amd64_hpet_timestamp () - start) * hpet_clock_nano) < conv)
__asm__ volatile ("pause" ::: "memory"); __asm__ volatile ("pause" ::: "memory");
spin_unlock (&hpet_lock);
} }
void amd64_hpet_init (void) { 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; 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;
} }

View File

@@ -3,7 +3,7 @@
#include <libk/std.h> #include <libk/std.h>
uint64_t amd64_hpet_current_nano (void); uint64_t amd64_hpet_current_nano (bool lock);
void amd64_hpet_sleep_micro (uint64_t us); void amd64_hpet_sleep_micro (uint64_t us);
void amd64_hpet_init (void); void amd64_hpet_init (void);