Fix HPET unaligned read/writes on bochs
This commit is contained in:
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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 (;;)
|
||||||
;
|
;
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user