Skip to content

Commit

Permalink
fix: fix for x86_64 timer
Browse files Browse the repository at this point in the history
  • Loading branch information
yfblock committed Jun 2, 2024
1 parent 1843db9 commit 88420a5
Show file tree
Hide file tree
Showing 9 changed files with 98 additions and 22 deletions.
2 changes: 1 addition & 1 deletion src/aarch64/gic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ impl IRQVector {
}
}

/// Get the irq Vector that was
/// Get the irq Vector that was
#[inline]
pub fn get_irq() -> IRQVector {
IRQVector(GICC.iar() as _)
Expand Down
9 changes: 5 additions & 4 deletions src/aarch64/trap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,10 @@ use aarch64_cpu::registers::{Writeable, ESR_EL1, FAR_EL1, SCTLR_EL2::I, VBAR_EL1
use tock_registers::interfaces::Readable;

use crate::{
currrent_arch::{gic::TIMER_IRQ_NUM, timer::set_next_timer}, instruction::Instruction, irq::IRQVector, TrapType
currrent_arch::{gic::TIMER_IRQ_NUM, timer::set_next_timer},
instruction::Instruction,
irq::IRQVector,
TrapType,
};

use super::{gic::get_irq, TrapFrame};
Expand Down Expand Up @@ -41,9 +44,7 @@ fn handle_exception(tf: &mut TrapFrame, kind: TrapKind, source: TrapSource) -> T
set_next_timer();
TrapType::Time
}
_ => {
TrapType::Irq(irq)
}
_ => TrapType::Irq(irq),
};
unsafe { crate::api::_interrupt_for_arch(tf, trap_type) };
return trap_type;
Expand Down
4 changes: 2 additions & 2 deletions src/irq.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,11 @@
/// [IRQ::int_enable]
/// // Enable interrupt
/// IRQ::int_enable();
///
///
/// [IRQ::int_disable]
/// // Disable interrupt
/// IRQ::int_disable();
///
///
/// [IRQ::int_enabled]
/// // Check if interrupt is enabled
/// let enabled = IRQ::int_enabled();
Expand Down
5 changes: 0 additions & 5 deletions src/x86_64/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -97,11 +97,6 @@ impl TrapFrame {
// 创建上下文信息
#[inline]
pub fn new() -> Self {
debug!(
"new_user cs: {:#x}, ss: {:#x}",
GdtStruct::UCODE64_SELECTOR.0,
GdtStruct::UDATA_SELECTOR.0
);
Self {
cs: GdtStruct::UCODE64_SELECTOR.0 as _,
ss: GdtStruct::UDATA_SELECTOR.0 as _,
Expand Down
6 changes: 4 additions & 2 deletions src/x86_64/interrupt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,10 @@ fn kernel_callback(context: &mut TrapFrame) {
context
);
}
APIC_TIMER_VECTOR => TrapType::Time,
APIC_TIMER_VECTOR => {
unsafe { super::apic::local_apic().end_of_interrupt() };
TrapType::Time
}
// IRQ_VECTOR_START..=IRQ_VECTOR_END => crate::trap::handle_irq_extern(tf.vector as _),
_ => {
panic!(
Expand All @@ -108,7 +111,6 @@ fn kernel_callback(context: &mut TrapFrame) {
}
};
unsafe { crate::api::_interrupt_for_arch(context, trap_type) };
unsafe { super::apic::local_apic().end_of_interrupt() };
}

#[naked]
Expand Down
1 change: 0 additions & 1 deletion src/x86_64/irq.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@

use crate::irq::{IRQVector, IRQ};

/// Implement IRQ operations for the IRQ interface.
Expand Down
6 changes: 6 additions & 0 deletions src/x86_64/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,12 @@ fn rust_tmp_main(magic: usize, mboot_ptr: usize) {
CpuId::new().get_feature_info().map(|features| {
info!("is there a avx feature: {}", features.has_avx());
info!("is there a xsave feature: {}", features.has_xsave());
// Add OSXSave flag to cr4 register if supported
if features.has_xsave() {
unsafe {
Cr4::write(Cr4::read() | Cr4Flags::OSXSAVE);
}
}
info!("cr4 has OSXSAVE feature: {:?}", Cr4::read());
if features.has_avx() && features.has_xsave() && Cr4::read().contains(Cr4Flags::OSXSAVE) {
unsafe {
Expand Down
12 changes: 11 additions & 1 deletion src/x86_64/multiboot.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,17 +17,27 @@ const MULTIBOOT_HEADER_FLAGS: usize = 0x0001_0002;
/// The magic field should contain this.
const MULTIBOOT_HEADER_MAGIC: usize = 0x1BADB002;

/// CR0 Registers introduction: https://wiki.osdev.org/CPU_Registers_x86-64#CR0
const CR0: u64 = Cr0Flags::PROTECTED_MODE_ENABLE.bits()
| Cr0Flags::MONITOR_COPROCESSOR.bits()
| Cr0Flags::NUMERIC_ERROR.bits()
| Cr0Flags::WRITE_PROTECT.bits()
| Cr0Flags::PAGING.bits();

/// CR4 registers introduction: https://wiki.osdev.org/CPU_Registers_x86-64#CR4
/// Physical Address Extension
const CR4: u64 = Cr4Flags::PHYSICAL_ADDRESS_EXTENSION.bits()
// Page Global Enable
| Cr4Flags::PAGE_GLOBAL.bits()
// OS support for fxsave and fxrstor instructions
| Cr4Flags::OSFXSR.bits()
| Cr4Flags::OSXSAVE.bits()
// XSAVE And Processor Extended States Enable
// This bit should open if the processor was supported.
// | Cr4Flags::OSXSAVE.bits()
// OS Support for unmasked simd floating point exceptions
| Cr4Flags::OSXMMEXCPT_ENABLE.bits();

/// EFER registers introduction: https://wiki.osdev.org/CPU_Registers_x86-64#IA32_EFER
const EFER: u64 = EferFlags::LONG_MODE_ENABLE.bits() | EferFlags::NO_EXECUTE_ENABLE.bits();

static mut MEM: Mem = Mem;
Expand Down
75 changes: 69 additions & 6 deletions src/x86_64/time.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
use raw_cpuid::CpuId;
use x86_64::structures::port::{self, PortRead};

use crate::time::Time;

static mut INIT_TICK: usize = 0;
static mut CPU_FREQ_MHZ: usize = 4000_000_000;

impl Time {
Expand Down Expand Up @@ -31,17 +31,80 @@ pub(super) fn init_early() {
}
}

unsafe { INIT_TICK = core::arch::x86_64::_rdtsc() as _ };
debug!("INIT_TICK: {}", unsafe { INIT_TICK });

unsafe {
use x2apic::lapic::{TimerDivide, TimerMode};
let lapic = super::apic::local_apic();
lapic.set_timer_mode(TimerMode::Periodic);
lapic.set_timer_divide(TimerDivide::Div256); // indeed it is Div1, the name is confusing.
lapic.set_timer_divide(TimerDivide::Div2); // indeed it is Div1, the name is confusing.
lapic.enable_timer();

lapic.set_timer_initial(0x20_0000);
// PIT(Programmable Interval Timer)
// https://wiki.osdev.org/Pit
// Bits Usage
// 6 and 7 Select channel :
// 0 0 = Channel 0
// 0 1 = Channel 1
// 1 0 = Channel 2
// 1 1 = Read-back command (8254 only)
// 4 and 5 Access mode :
// 0 0 = Latch count value command
// 0 1 = Access mode: lobyte only
// 1 0 = Access mode: hibyte only
// 1 1 = Access mode: lobyte/hibyte
// 1 to 3 Operating mode :
// 0 0 0 = Mode 0 (interrupt on terminal count)
// 0 0 1 = Mode 1 (hardware re-triggerable one-shot)
// 0 1 0 = Mode 2 (rate generator)
// 0 1 1 = Mode 3 (square wave generator)
// 1 0 0 = Mode 4 (software triggered strobe)
// 1 0 1 = Mode 5 (hardware triggered strobe)
// 1 1 0 = Mode 2 (rate generator, same as 010b)
// 1 1 1 = Mode 3 (square wave generator, same as 011b)
// 0 BCD/Binary mode: 0 = 16-bit binary, 1 = four-digit BCD
// open PIT2
let pcspeaker = u8::read_from_port(0x61);
u8::write_to_port(0x61, pcspeaker | 1);

const PIT_FREQ: u16 = 11931;
use port::PortWrite;
// Set PIT2 one-shott mode
u8::write_to_port(0x43, 0b10110010);

// Write frequency to port
u16::write_to_port(0x42, PIT_FREQ & 0xff);
u16::write_to_port(0x42, (PIT_FREQ >> 8) & 0xff);

// Reset PIT2 counter
let pcspeaker = u8::read_from_port(0x61);
u8::write_to_port(0x61, pcspeaker & 0xfd);
u8::write_to_port(0x61, pcspeaker | 1);

// Reset loapic counter
lapic.set_timer_initial(0xFFFF_FFFF);

// Read count
loop {
let mut count = u16::read_from_port(0x42);
count |= u16::read_from_port(0x42) << 8;
if count == 0 || count >= 60000 {
break;
}
}
let end = lapic.timer_current();
log::info!(
"end {:#x} start: {:#x}, interval: {:#x}",
end,
0xFFFF_FFFFu32,
0xFFFF_FFFF - end
);

let ticks10ms = 0xFFFF_FFFF - end;
// lapic.set_timer_initial(0x20_000);
// Set ticks 1s
log::info!("ticks 50us: {}", ticks10ms / 10 / 20);
// lapic.set_timer_initial(ticks10ms * 0x100);
// Set 500us ticks
lapic.set_timer_initial(ticks10ms / 20);
debug!("count: {}", lapic.timer_current());
// set_oneshot_timer(2000);
}
Expand Down

0 comments on commit 88420a5

Please sign in to comment.