summaryrefslogtreecommitdiff
path: root/kernel/src/arch/x86_64
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/src/arch/x86_64')
-rw-r--r--kernel/src/arch/x86_64/cpu/gdt.cpp2
-rw-r--r--kernel/src/arch/x86_64/cpu/idt.cpp2
-rw-r--r--kernel/src/arch/x86_64/cpu/lapic.cpp4
-rw-r--r--kernel/src/arch/x86_64/cpu/sse.cpp4
-rw-r--r--kernel/src/arch/x86_64/cpu_local.hpp22
-rw-r--r--kernel/src/arch/x86_64/drivers/hpet.cpp4
-rw-r--r--kernel/src/arch/x86_64/drivers/ioapic.cpp4
-rw-r--r--kernel/src/arch/x86_64/drivers/pvclock.cpp40
-rw-r--r--kernel/src/arch/x86_64/drivers/tsc.cpp4
-rw-r--r--kernel/src/arch/x86_64/schedule_timer.cpp4
10 files changed, 62 insertions, 28 deletions
diff --git a/kernel/src/arch/x86_64/cpu/gdt.cpp b/kernel/src/arch/x86_64/cpu/gdt.cpp
index 0498c21..f2adea1 100644
--- a/kernel/src/arch/x86_64/cpu/gdt.cpp
+++ b/kernel/src/arch/x86_64/cpu/gdt.cpp
@@ -47,6 +47,6 @@ void x86_64::gdt::init() {
cpudata->timer_ist_stack = (std::uint64_t)(pmm::buddy::alloc(KERNEL_STACK_SIZE).phys + etc::hhdm());
static bool is_print = 0;
- if(!is_print) { klibc::printf("GDT: tss->rsp0 0x%p tss->ist0 0x%p\r\n",tss->rsp[0],tss->ist[0],tss->ist[1],tss->ist[2],tss->ist[3],cpudata->timer_ist_stack); is_print = 1; }
+ if(!is_print) { log("gdt", "tss->rsp0 0x%p tss->ist0 0x%p",tss->rsp[0],tss->ist[0],tss->ist[1],tss->ist[2],tss->ist[3],cpudata->timer_ist_stack); is_print = 1; }
} \ No newline at end of file
diff --git a/kernel/src/arch/x86_64/cpu/idt.cpp b/kernel/src/arch/x86_64/cpu/idt.cpp
index c62b1e6..def3341 100644
--- a/kernel/src/arch/x86_64/cpu/idt.cpp
+++ b/kernel/src/arch/x86_64/cpu/idt.cpp
@@ -43,7 +43,7 @@ void x86_64::idt::init() {
load();
- if(!is_print) {klibc::printf("IDT: IDTR is 0x%p\r\n",&idtr); is_print = 1;}
+ if(!is_print) {log("idt", "idtr is 0x%p",&idtr); is_print = 1;}
}
void x86_64::idt::load() {
diff --git a/kernel/src/arch/x86_64/cpu/lapic.cpp b/kernel/src/arch/x86_64/cpu/lapic.cpp
index 3bea37c..da98bfd 100644
--- a/kernel/src/arch/x86_64/cpu/lapic.cpp
+++ b/kernel/src/arch/x86_64/cpu/lapic.cpp
@@ -32,7 +32,7 @@ std::uint64_t x86_64::lapic::init(std::uint32_t us) {
if(c & (1 << 21)) {
// x2apic present
- if(!is_print) klibc::printf("X2APIC: Enabling x2apic (base is 0x%p)\r\n",0x800);
+ if(!is_print) log("x2apic", "enabling x2apic (base is 0x%p)",0x800);
assembly::wrmsr(0x1B,assembly::rdmsr(0x1B) | (1 << 10) | (1 << 11));
is_x2apic = 1;
} else {
@@ -52,7 +52,7 @@ std::uint64_t x86_64::lapic::init(std::uint32_t us) {
write(0x380,ticks);
if(!is_lapic_init) {
- if(!is_print) klibc::printf("LAPIC: Calibration time is %lli, ticks %lli\r\n",us,ticks);
+ if(!is_print) log("lapic", "calibration time is %lli, ticks %lli",us,ticks);
is_print = 1;
is_lapic_init = 1;
}
diff --git a/kernel/src/arch/x86_64/cpu/sse.cpp b/kernel/src/arch/x86_64/cpu/sse.cpp
index 73d53ae..b71ed10 100644
--- a/kernel/src/arch/x86_64/cpu/sse.cpp
+++ b/kernel/src/arch/x86_64/cpu/sse.cpp
@@ -120,8 +120,8 @@ void x86_64::sse::print_sse_features() {
std::uint32_t a,b,c,d;
assembly::cpuid(1,0,&a,&b,&c,&d);
- klibc::printf(
- "SSE: Supported features:" "%s%s%s%s%s%s\n",
+ log( "sse",
+ "supported features:" "%s%s%s%s%s%s",
(d & (1 << 25)) ? " SSE" : "\0",
(d & (1 << 26)) ? " SSE2" : "\0",
(c & (1 << 0)) ? " SSE3\0" : "\0",
diff --git a/kernel/src/arch/x86_64/cpu_local.hpp b/kernel/src/arch/x86_64/cpu_local.hpp
index d5add64..152e6fc 100644
--- a/kernel/src/arch/x86_64/cpu_local.hpp
+++ b/kernel/src/arch/x86_64/cpu_local.hpp
@@ -7,9 +7,11 @@
#include <generic/scheduling.hpp>
#include <klibc/string.hpp>
#include <klibc/stdio.hpp>
+#include <cstddef>
+#include <type_traits>
#include <generic/arch.hpp>
-typedef struct {
+struct cpudata_t {
std::uint64_t user_stack;
std::uint64_t kernel_stack;
std::uint64_t timer_ist_stack;
@@ -17,7 +19,7 @@ typedef struct {
std::uint64_t tsc_freq;
void* pvclock_buffer;
thread* current_thread;
-} cpudata_t;
+};
namespace x86_64 {
@@ -45,4 +47,20 @@ namespace x86_64 {
}
return (cpudata_t*)cpudata;
}
+
+ template <typename T, std::size_t Offset> [[nodiscard]] static inline T cpu_local_read() {
+ T out;
+ asm volatile("mov %%gs:%c1, %0" : "=r"(out) : "i"(Offset));
+ return out;
+ }
+
+ template <typename T, std::size_t Offset, typename V> static inline void cpu_local_write(V&& value) {
+ static_assert(std::is_same_v<std::remove_cvref_t<V>, std::remove_cv_t<T>>, "member type and value type are not compatible");
+ T v = static_cast<T>(value);
+ asm volatile("mov %0, %%gs:%c1" : : "r"(v), "i"(Offset));
+ }
+
};
+
+#define CPU_LOCAL_READ(field) x86_64::cpu_local_read<decltype(((cpudata_t*) nullptr)->field), offsetof(cpudata_t, field)>()
+#define CPU_LOCAL_WRITE(field, value) x86_64::cpu_local_write<decltype(((cpudata_t*) nullptr)->field), offsetof(cpudata_t, field)>((value)) \ No newline at end of file
diff --git a/kernel/src/arch/x86_64/drivers/hpet.cpp b/kernel/src/arch/x86_64/drivers/hpet.cpp
index 152f0d9..5421157 100644
--- a/kernel/src/arch/x86_64/drivers/hpet.cpp
+++ b/kernel/src/arch/x86_64/drivers/hpet.cpp
@@ -23,7 +23,7 @@ void drivers::hpet::init() {
uacpi_table hpet;
uacpi_status ret = uacpi_table_find_by_signature("HPET",&hpet);
if(ret != UACPI_STATUS_OK) {
- klibc::printf("HPET: hpet is not detected with status %d\r\n",ret);
+ log("hpet", "hpet is not detected with status %d",ret);
return;
}
@@ -36,7 +36,7 @@ void drivers::hpet::init() {
hpet_clock_nano = (*(volatile uint32_t*)(hpet_base + 4)) / 1000000;
hpet_timer* new_hpet_inst = new hpet_timer;
time::setup_timer(new_hpet_inst);
- klibc::printf("HPET: Detected %s hpet, current timestamp in nano %lli (hpet_base 0x%p)\r\n",hpet_is_32_bit ? "32 bit" : "64 bit", new_hpet_inst->current_nano(),hpet_base);
+ log("hpet", "Detected %s hpet, current timestamp in nano %lli (hpet_base 0x%p)",hpet_is_32_bit ? "32 bit" : "64 bit", new_hpet_inst->current_nano(),hpet_base);
}
namespace drivers {
diff --git a/kernel/src/arch/x86_64/drivers/ioapic.cpp b/kernel/src/arch/x86_64/drivers/ioapic.cpp
index 4b9c04a..ee5170f 100644
--- a/kernel/src/arch/x86_64/drivers/ioapic.cpp
+++ b/kernel/src/arch/x86_64/drivers/ioapic.cpp
@@ -41,13 +41,13 @@ void drivers::ioapic::init() {
struct acpi_madt_ioapic* cur_ioapic = (acpi_madt_ioapic*)current;
paging::map_range(gobject::kernel_root,cur_ioapic->address,cur_ioapic->address + etc::hhdm(),PAGE_SIZE,PAGING_PRESENT | PAGING_RW);
apics[apic_ent++] = *cur_ioapic;
- klibc::printf("IOAPIC: Found ioapic with gsi base %d, address 0x%p, id %d\r\n",cur_ioapic->gsi_base,cur_ioapic->address,cur_ioapic->id);
+ log("ioapic", "Found ioapic with gsi base %d, address 0x%p, id %d",cur_ioapic->gsi_base,cur_ioapic->address,cur_ioapic->id);
break;
}
case ACPI_MADT_ENTRY_TYPE_INTERRUPT_SOURCE_OVERRIDE: {
struct acpi_madt_interrupt_source_override* cur_iso = (struct acpi_madt_interrupt_source_override*)current;
iso[iso_ent++] = *cur_iso;
- klibc::printf("IOAPIC: Found ISO with bus %d, irq %d, gsi base %d, flags %d\r\n",cur_iso->bus,cur_iso->source,cur_iso->gsi,cur_iso->flags);
+ log("ioapic", "Found ISO with bus %d, irq %d, gsi base %d, flags %d",cur_iso->bus,cur_iso->source,cur_iso->gsi,cur_iso->flags);
break;
}
}
diff --git a/kernel/src/arch/x86_64/drivers/pvclock.cpp b/kernel/src/arch/x86_64/drivers/pvclock.cpp
index d77ef0f..db19120 100644
--- a/kernel/src/arch/x86_64/drivers/pvclock.cpp
+++ b/kernel/src/arch/x86_64/drivers/pvclock.cpp
@@ -43,26 +43,42 @@ void drivers::pvclock::bsp_init() {
drivers::pvclock_timer* timer = new drivers::pvclock_timer;
time::setup_timer(timer);
- klibc::printf("pvclock: pointer to buffer 0x%p\r\n",x86_64::cpu_data()->pvclock_buffer);
+ log("pvclock", "pointer to buffer 0x%p",x86_64::cpu_data()->pvclock_buffer);
}
namespace drivers {
std::uint64_t pvclock_timer::current_nano() {
- uint32_t lo, hi;
- asm volatile ("rdtsc" : "=a"(lo), "=d"(hi));
- std::uint64_t tsc_v = ((uint64_t)hi << 32) | lo;
- pvclock_vcpu_time_info* kvmclock_info = (pvclock_vcpu_time_info*)(x86_64::cpu_data()->pvclock_buffer);
- std::uint64_t time0 = tsc_v - kvmclock_info->tsc_timestamp;
- if(kvmclock_info->tsc_shift >= 0)
- time0 <<= kvmclock_info->tsc_shift;
- else
- time0 >>= -kvmclock_info->tsc_shift;
- time0 = (time0 * kvmclock_info->tsc_to_system_mul) >> 32;
- time0 = time0 + kvmclock_info->system_time;
+ auto* info = (pvclock_vcpu_time_info*)CPU_LOCAL_READ(pvclock_buffer);
+ uint32_t version;
+ uint64_t time0;
+
+ do {
+ version = info->version;
+ std::atomic_thread_fence(std::memory_order_acquire);
+
+ uint32_t lo, hi;
+ asm volatile ("rdtsc" : "=a"(lo), "=d"(hi) : : "memory");
+ uint64_t tsc_v = (static_cast<uint64_t>(hi) << 32) | lo;
+
+ uint64_t delta = tsc_v - info->tsc_timestamp;
+
+ if (info->tsc_shift >= 0)
+ delta <<= info->tsc_shift;
+ else
+ delta >>= -info->tsc_shift;
+
+ uint64_t scaled_delta = (static_cast<unsigned __int128>(delta) * info->tsc_to_system_mul) >> 32;
+
+ time0 = info->system_time + scaled_delta;
+
+ std::atomic_thread_fence(std::memory_order_acquire);
+ } while ((info->version & 1) || (info->version != version));
+
return time0;
}
+
void pvclock_timer::sleep(std::uint64_t us) {
std::uint64_t current = this->current_nano();
std::uint64_t end_ns = us * 1000;
diff --git a/kernel/src/arch/x86_64/drivers/tsc.cpp b/kernel/src/arch/x86_64/drivers/tsc.cpp
index 3776144..4203d76 100644
--- a/kernel/src/arch/x86_64/drivers/tsc.cpp
+++ b/kernel/src/arch/x86_64/drivers/tsc.cpp
@@ -17,7 +17,7 @@ static inline uint64_t rdtsc() {
void drivers::tsc::init() {
if(time::timer == nullptr) {
- klibc::printf("TSC: Can't initialize without timer !\n");
+ log("tsc", "can't initialize without timer !");
}
uint64_t tsc_start, tsc_end;
@@ -55,7 +55,7 @@ void drivers::tsc::init() {
x86_64::cpu_data()->tsc_freq = tsc_freq;
static bool is_print = 0;
- if(!is_print) {klibc::printf("TSC: TSC Frequency is %llu\r\n", tsc_freq); is_print = 1;}
+ if(!is_print) {log("tsc", "tsc frequency is %llu", tsc_freq); is_print = 1;}
drivers::tsc_timer* tsc_timer = new drivers::tsc_timer;
time::setup_timer(tsc_timer);
}
diff --git a/kernel/src/arch/x86_64/schedule_timer.cpp b/kernel/src/arch/x86_64/schedule_timer.cpp
index 97882c7..60bb649 100644
--- a/kernel/src/arch/x86_64/schedule_timer.cpp
+++ b/kernel/src/arch/x86_64/schedule_timer.cpp
@@ -35,12 +35,12 @@ void x86_64::schedule_timer::off() {
std::uint32_t timeout = 10;
- klibc::printf("Poweroff: Waiting for all cpus to done work\r\n"); // used from poweroff so
+ log("poweroff", "waiting for all cpus to done work"); // used from poweroff so
while(stfu_cpus != (std::int32_t)(mp::cpu_count() - 1)) {
arch::memory_barrier();
if(--timeout == 0) {
- klibc::printf("Poweroff: Can't wait longer, forching them to be disabled\r\n");
+ log("poweroff", "poweroff: Can't wait longer, forcing them to be disabled");
x86_64::lapic::off();
return;
}