Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement HPET driver #256

Merged
merged 11 commits into from
May 15, 2019
Merged

Implement HPET driver #256

merged 11 commits into from
May 15, 2019

Conversation

marysaka
Copy link
Member

This PR adds support for the "High Precision Event Timer" device.

This permits us to get better timing resolution (PIC resolution was 10ms, we now have a resolution of 100ns)

As we currently don't have IO-APIC support, the HPET is setup in "legacy mapping" and use the IRQ0 and IRQ8 for timer 0 and timer 1.
This result in the RTC device not being able to send interrupt.
For this matter, the timer 1 is setup to send an interrupt every seconds to fake this until we get IO-APIC support.

Makefile.toml Outdated Show resolved Hide resolved
kernel/src/i386/acpi.rs Outdated Show resolved Hide resolved
kernel/src/i386/acpi.rs Outdated Show resolved Hide resolved
kernel/src/devices/hpet.rs Outdated Show resolved Hide resolved
@marysaka
Copy link
Member Author

Ready for reviews

Thog and others added 8 commits April 21, 2019 13:11
TODO: IOAPIC LOCAL APIC
TODO: enable main timer and wrap the wait event in some interface
instead of using pit directly.
Also fake RTC irq as it's used by the hpet.
Also fix HPET frequency to 100ns
Also remove dead code
Somehow KVM doesn't use ACPI, fix issues on this.
Now ACPI is detected on KVM environments.

Also updated multiboot2 crate to latest with our custom patches.
@todo
Copy link

todo bot commented Apr 21, 2019

Test the hardware behaviour on partial write of the HPET accumulator

Because we are running on i386, this cause issue on QEMU. In fact, QEMU clear the accumulator flag on every partial write. The question here is: Is that normal or a bug in QEMU?


// TODO: Test the hardware behaviour on partial write of the HPET accumulator
// BODY: Because we are running on i386, this cause issue on QEMU.
// BODY: In fact, QEMU clear the accumulator flag on every partial write.
// BODY: The question here is: Is that normal or a bug in QEMU?
let mut config = unsafe { (*self.inner).config.read() };
config.set_accumulator_config(true);
unsafe { (*self.inner).config.write(config) };
unsafe {
(*self.inner)
.comparator_value_low
.write((value & 0xFFFF_FFFF) as u32)


This comment was generated by todo based on a TODO comment in 8e5ee83 in #256. cc @Thog.

@todo
Copy link

todo bot commented Apr 21, 2019

enable main timer

// TODO: enable main timer
let main_timer_opt = hpet_instance.get_timer(0);
if main_timer_opt.is_none() {
paging::kernel_memory::get_kernel_memory().unmap(virtual_address, PAGE_SIZE);
return false;
}
// Set the tick rate in femtoseconds
// Kernel needs an update frequency of 100 nanoseconds.
let tick_rate = 100;


This comment was generated by todo based on a TODO comment in 8e5ee83 in #256. cc @Thog.

@todo
Copy link

todo bot commented Apr 21, 2019

remove this when IO-APIC will be implemented

// TODO: remove this when IO-APIC will be implemented
// Cannot fail, by spec there is at least 3 comparators defined.
let rtc_timer = hpet_instance.get_timer(1).unwrap();
if !rtc_timer.support_periodic_interrupt() {
warn!("RTC irq cannot be faked, clock will be broken!");
} else {
let rtc_frequency = hpet_instance.get_frequency();
rtc_timer.set_edge_trigger();
rtc_timer.set_periodic_mode();
rtc_timer.enable_interrupt();
rtc_timer.set_accumulator_value(rtc_frequency);


This comment was generated by todo based on a TODO comment in 8e5ee83 in #256. cc @Thog.

@todo
Copy link

todo bot commented Apr 21, 2019

switch HPET to normal mode when IO-APIC will be implemented.

// TODO: switch HPET to normal mode when IO-APIC will be implemented.
hpet_instance.enable_legacy_mapping();
// Clear the interrupt state
hpet_instance.enable();
timer::set_kernel_timer_info(0, hpet_instance.get_frequency(), tick_rate);
HPET_INSTANCE = Some(hpet_instance);
true
}


This comment was generated by todo based on a TODO comment in 8e5ee83 in #256. cc @Thog.

@marysaka
Copy link
Member Author

Rebased

Copy link
Member

@Orycterope Orycterope left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Math is hard

kernel/src/frame_allocator/physical_mem_region.rs Outdated Show resolved Hide resolved
kernel/src/i386/acpi.rs Outdated Show resolved Hide resolved
kernel/src/timer.rs Show resolved Hide resolved
kernel/src/timer.rs Outdated Show resolved Hide resolved
kernel/src/timer.rs Outdated Show resolved Hide resolved
kernel/src/devices/pit.rs Outdated Show resolved Hide resolved
kernel/src/devices/hpet.rs Outdated Show resolved Hide resolved
kernel/src/devices/hpet.rs Outdated Show resolved Hide resolved
kernel/src/devices/hpet.rs Show resolved Hide resolved
kernel/src/devices/hpet.rs Outdated Show resolved Hide resolved
@Orycterope
Copy link
Member

I don't recall what was the precise reason of this PR ? Did we need a higher precision timer somewhere ? Is this a necessary step to some goal ?

@marysaka
Copy link
Member Author

marysaka commented May 9, 2019

@Orycterope This is a preparation to get the LAPIC and IO-APIC implemented (and then multicore). The final goal of this is to have multiple timer on multiple core.

@todo
Copy link

todo bot commented May 9, 2019

Switch to a lower update frequency in HPET

We will maybe prefer to have a better resolution for kernel time. For that to be possible, we need to take care of the sleep_thread logic in userland first (sleep_thread(0) shouldn't be used).


// TODO: Switch to a lower update frequency in HPET
// BODY: We will maybe prefer to have a better resolution for kernel time.
// BODY: For that to be possible, we need to take care of the sleep_thread logic in userland first (sleep_thread(0) shouldn't be used).
let irq_period_ns = 1 * 1_000_000;
let irq_period_fs = irq_period_ns * 1_000_000;
info!("HPET frequency: {} Hz", hpet_instance.get_frequency());
info!("HPET IRQ period: {} fs", irq_period_fs);
let kernel_frequency = irq_period_fs / u64::from(hpet_instance.get_period());


This comment was generated by todo based on a TODO comment in dce8599 in #256. cc @Thog.

kernel/src/devices/hpet.rs Outdated Show resolved Hide resolved
kernel/src/devices/hpet.rs Outdated Show resolved Hide resolved
kernel/src/devices/hpet.rs Show resolved Hide resolved
@marysaka marysaka requested a review from Orycterope May 15, 2019 16:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants