pub fn init(
+init in captain - Rust pub fn init(
kernel_mmi_ref: MmiRef,
bsp_initial_stack: NoDrop<Stack>,
drop_after_init: DropAfterInit,
diff --git a/doc/captain/index.html b/doc/captain/index.html
index c1551461c9..1ab1a36ea0 100644
--- a/doc/captain/index.html
+++ b/doc/captain/index.html
@@ -1,4 +1,4 @@
-captain - Rust Expand description
The main initialization routine and setup logic of the OS.
+captain - Rust Expand description
The main initialization routine and setup logic of the OS.
The captain
steers the ship of Theseus, meaning that it contains basic logic
for initializing all of the other crates in the proper order and with
the proper flow of data between them.
diff --git a/doc/crates.js b/doc/crates.js
index c1c745f991..3ce3b09ea0 100644
--- a/doc/crates.js
+++ b/doc/crates.js
@@ -1 +1 @@
-window.ALL_CRATES = ["___Theseus_Crates___","acpi","acpi_table","acpi_table_handler","ap_start","apic","app_io","arm_boards","async_channel","ata","atomic_linked_list","block_allocator","block_cache","boot_info","bootloader_modules","captain","catch_unwind","cls","cls_allocator","cls_macros","color","compositor","console","context_switch","context_switch_avx","context_switch_regular","context_switch_sse","cow_arc","cpu","crate_metadata","crate_metadata_serde","crate_name_utils","crate_swap","debug_info","debugit","deferred_interrupt_tasks","dereffer","device_manager","dfqueue","displayable","dmar","dreadnought","e1000","early_printer","early_tls","environment","event_types","exceptions_early","exceptions_full","external_unwind_info","fadt","fault_crate_swap","fault_log","first_application","font","frame_allocator","framebuffer","framebuffer_compositor","framebuffer_drawer","framebuffer_printer","fs_node","gdt","gic","heap","heapfile","hpet","http_client","idle","intel_ethernet","interrupt_controller","interrupts","io","ioapic","iommu","irq_safety","ixgbe","kernel_config","keyboard","keycodes_ascii","libterm","local_storage_initializer","lockable","locked_idt","logger","madt","memfs","memory","memory_aarch64","memory_initialization","memory_structs","memory_x86_64","mlx5","mlx_ethernet","mod_mgmt","mouse","mouse_data","multicore_bringup","multiple_heaps","nano_core","net","nic_buffers","nic_initialization","nic_queues","no_drop","ota_update_client","owned_borrowed_trait","page_allocator","page_attribute_table","page_table_entry","panic_entry","panic_wrapper","path","pci","percent_encoding","physical_nic","pic","pit_clock","pit_clock_basic","pmu_x86","port_io","preemption","ps2","pte_flags","random","range_inclusive","rendezvous","root","rsdp","rsdt","rtc","scheduler","scheduler_epoch","scheduler_priority","scheduler_round_robin","sdt","serial_port","serial_port_basic","shapes","signal_handler","simd_personality","simd_test","simple_ipc","single_simd_task_optimization","slabmalloc","slabmalloc_safe","slabmalloc_unsafe","sleep","spawn","stack","stack_trace","stack_trace_frame_pointers","state_store","stdio","storage_device","storage_manager","str_ref","sync_block","sync_preemption","task","task_fs","task_struct","text_display","text_terminal","theseus_features","thread_local_macro","time","tlb_shootdown","tsc","tss","tty","uart_pl011","unwind","vfs_node","vga_buffer","virtual_nic","waet","wait_condition","wait_guard","wait_queue","waker","waker_generic","wasi_interpreter","window","window_inner","window_manager"];
\ No newline at end of file
+window.ALL_CRATES = ["___Theseus_Crates___","acpi","acpi_table","acpi_table_handler","ap_start","apic","app_io","arm_boards","async_channel","ata","atomic_linked_list","block_allocator","block_cache","boot_info","bootloader_modules","captain","catch_unwind","cls","cls_allocator","cls_macros","color","compositor","console","context_switch","context_switch_avx","context_switch_regular","context_switch_sse","cow_arc","cpu","crate_metadata","crate_metadata_serde","crate_name_utils","crate_swap","debug_info","debugit","deferred_interrupt_tasks","dereffer","device_manager","dfqueue","displayable","dmar","dreadnought","e1000","early_printer","early_tls","environment","event_types","exceptions_early","exceptions_full","external_unwind_info","fadt","fault_crate_swap","fault_log","first_application","font","frame_allocator","framebuffer","framebuffer_compositor","framebuffer_drawer","framebuffer_printer","fs_node","gdt","generic_timer_aarch64","gic","heap","heapfile","hpet","http_client","idle","intel_ethernet","interrupt_controller","interrupts","io","ioapic","iommu","irq_safety","ixgbe","kernel_config","keyboard","keycodes_ascii","libterm","local_storage_initializer","lockable","locked_idt","logger","madt","memfs","memory","memory_aarch64","memory_initialization","memory_structs","memory_x86_64","mlx5","mlx_ethernet","mod_mgmt","mouse","mouse_data","multicore_bringup","multiple_heaps","nano_core","net","nic_buffers","nic_initialization","nic_queues","no_drop","ota_update_client","owned_borrowed_trait","page_allocator","page_attribute_table","page_table_entry","panic_entry","panic_wrapper","path","pci","percent_encoding","physical_nic","pic","pit_clock","pit_clock_basic","pmu_x86","port_io","preemption","ps2","pte_flags","random","range_inclusive","rendezvous","root","rsdp","rsdt","rtc","scheduler","scheduler_epoch","scheduler_priority","scheduler_round_robin","sdt","serial_port","serial_port_basic","shapes","signal_handler","simd_personality","simd_test","simple_ipc","single_simd_task_optimization","slabmalloc","slabmalloc_safe","slabmalloc_unsafe","sleep","spawn","stack","stack_trace","stack_trace_frame_pointers","state_store","stdio","storage_device","storage_manager","str_ref","sync_block","sync_preemption","task","task_fs","task_struct","text_display","text_terminal","theseus_features","thread_local_macro","time","tlb_shootdown","tsc","tss","tty","uart_pl011","unwind","vfs_node","vga_buffer","virtual_nic","waet","wait_condition","wait_guard","wait_queue","waker","waker_generic","wasi_interpreter","window","window_inner","window_manager"];
\ No newline at end of file
diff --git a/doc/generic_timer_aarch64/all.html b/doc/generic_timer_aarch64/all.html
new file mode 100644
index 0000000000..8be983d212
--- /dev/null
+++ b/doc/generic_timer_aarch64/all.html
@@ -0,0 +1 @@
+List of all items in this crate List of all items
\ No newline at end of file
diff --git a/doc/generic_timer_aarch64/index.html b/doc/generic_timer_aarch64/index.html
new file mode 100644
index 0000000000..922b826e5d
--- /dev/null
+++ b/doc/generic_timer_aarch64/index.html
@@ -0,0 +1,3 @@
+generic_timer_aarch64 - Rust Crate generic_timer_aarch64
source · Expand description
Support for aarch64’s generic timer and system counter.
+Docs: https://developer.arm.com/documentation/102379/latest/
+
\ No newline at end of file
diff --git a/doc/generic_timer_aarch64/sidebar-items.js b/doc/generic_timer_aarch64/sidebar-items.js
new file mode 100644
index 0000000000..5244ce01cc
--- /dev/null
+++ b/doc/generic_timer_aarch64/sidebar-items.js
@@ -0,0 +1 @@
+window.SIDEBAR_ITEMS = {};
\ No newline at end of file
diff --git a/doc/scheduler/index.html b/doc/scheduler/index.html
index 1269974e89..47a42c80a1 100644
--- a/doc/scheduler/index.html
+++ b/doc/scheduler/index.html
@@ -1,4 +1,4 @@
-scheduler - Rust Expand description
Offers the ability to control or configure the active task scheduling policy.
+scheduler - Rust Expand description
Offers the ability to control or configure the active task scheduling policy.
What is and isn’t in this crate?
This crate also defines the timer interrupt handler used for preemptive
task switching on each CPU. In init()
, it registers that handler
diff --git a/doc/search-index.js b/doc/search-index.js
index de92b1af36..fa57c8aeff 100644
--- a/doc/search-index.js
+++ b/doc/search-index.js
@@ -61,6 +61,7 @@ var searchIndex = JSON.parse('{\
"framebuffer_printer":{"doc":"This crate contains functions to print strings in a …","t":"FFF","n":["fill_blank","print_ascii_character","print_string"],"q":[[0,"framebuffer_printer"]],"d":["Fill a blank text area (left, top, right, bottom) with …","Prints a character to the framebuffer at position (line, …","Prints a string in a framebuffer. Returns (column, line, …"],"i":[0,0,0],"f":[[[[2,[1]],3,1]],[[[2,[1]],4,1,1,5,6,6]],[[[2,[1]],5,6,6,7,1,1,6,6]]],"c":[],"p":[[8,"Pixel"],[3,"Framebuffer"],[3,"Rectangle"],[15,"u8"],[3,"Coord"],[15,"usize"],[15,"str"]]},\
"fs_node":{"doc":"Defines traits for Files and Directories within the …","t":"NGIINEGIGGKLLLLLLKLLLLKLKLKLLLLKKKLLLLL","n":["Dir","DirRef","Directory","File","File","FileOrDir","FileRef","FsNode","WeakDirRef","WeakFileRef","as_mapping","borrow","borrow_mut","clone","clone_into","fmt","from","get","get_absolute_path","get_absolute_path","get_dir","get_file","get_name","get_name","get_parent_dir","get_parent_dir","insert","into","is_dir","is_file","len","list","remove","set_parent_dir","set_parent_dir","to_owned","try_from","try_into","type_id"],"q":[[0,"fs_node"]],"d":["","A reference to any type that implements the Directory
…","Trait for directories, implementors of Directory must also …","","","Allows us to return a generic type that can be matched by …","A reference to any type that implements the File
trait, …","A trait that covers any filesystem node, both files and …","A weak reference to any type that implements the Directory
…","A weak reference to any type that implements the File
…","Returns a view of this file as an immutable memory-mapped …","","","","","","Returns the argument unchanged.","Gets either the file or directory in this Directory
on …","Recursively gets the absolute pathname as a String","","Like Directory::get()
, but only looks for directories …","Like Directory::get()
, but only looks for files matching …","Returns the string name of the node","","Returns the parent directory of the current node.","","Inserts the given new file or directory into this …","Calls U::from(self)
.","Returns true
if this is a Directory
, false
if it is a File
.","Returns true
if this is a File
, false
if it is a Directory
.","Returns the length (size) in bytes of this FileOrDir
.","Lists the names of the nodes in this directory.","Removes a file or directory from this directory and …","Sets this node’s parent directory. This is useful for …","","","","",""],"i":[4,0,0,0,4,0,0,0,0,0,16,4,4,4,4,4,4,17,18,4,17,17,18,4,18,4,17,4,4,4,4,17,17,18,4,4,4,4,4],"f":[0,0,0,0,0,0,0,0,0,0,[[],[[3,[1,2]]]],[[]],[[]],[4,4],[[]],[[4,5],6],[[]],[2,[[7,[4]]]],[[],8],[4,8],[2,[[7,[9]]]],[2,[[7,[10]]]],[[],8],[4,8],[[],[[7,[9]]]],[4,[[7,[9]]]],[4,[[3,[[7,[4]],2]]]],[[]],[4,11],[4,11],[4,12],[[],[[13,[8]]]],[4,[[7,[4]]]],[14],[[4,14]],[[]],[[],3],[[],3],[[],15]],"c":[],"p":[[3,"MappedPages"],[15,"str"],[4,"Result"],[4,"FileOrDir"],[3,"Formatter"],[6,"Result"],[4,"Option"],[3,"String"],[6,"DirRef"],[6,"FileRef"],[15,"bool"],[15,"usize"],[3,"Vec"],[6,"WeakDirRef"],[3,"TypeId"],[8,"File"],[8,"Directory"],[8,"FsNode"]]},\
"gdt":{"doc":"","t":"EEDNNNNNNNNNLLLLLLLLLFFLLLLLLLLLLLLLLLLLLLLLLLLLLLLL","n":["AvailableSegmentSelector","Descriptor","Gdt","KernelCode","KernelData","SystemSegment","Tss","UserCode32","UserCode64","UserData32","UserData64","UserSegment","add_entry","borrow","borrow","borrow","borrow_mut","borrow_mut","borrow_mut","clone","clone_into","create_and_load_tss_gdt","create_gdt","fmt","fmt","from","from","from","get","into","into","into","kernel_code_segment","kernel_data_segment","load","new","to_owned","to_string","try_from","try_from","try_from","try_into","try_into","try_into","tss_segment","type_id","type_id","type_id","user_code_32_segment","user_code_64_segment","user_data_32_segment","user_data_64_segment"],"q":[[0,"gdt"]],"d":["The GDT SegmentSelector
s available in Theseus.","The two kinds of descriptor entries in the GDT.","The Global Descriptor Table, as specified by the x86_64 …","","","SystemSegment is used only for TSS.","","","","","","UserSegment is used for both code and data segments, in …","","","","","","","","","","This function first creates and sets up a new TSS with the …","Creates and sets up a new GDT that refers to the given TSS
…","","","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the requested SegmentSelector
, or None
if it hasn…","Calls U::from(self)
.","Calls U::from(self)
.","Calls U::from(self)
.","","","","","","","","","","","","","","","","","","","",""],"i":[0,0,0,5,5,2,5,5,5,5,5,2,1,1,2,5,1,2,5,5,5,0,0,1,5,1,2,5,5,1,2,5,2,2,1,1,5,1,1,2,5,1,2,5,2,1,2,5,2,2,2,2],"f":[0,0,0,0,0,0,0,0,0,0,0,0,[[1,2,3],4],[[]],[[]],[[]],[[]],[[]],[[]],[5,5],[[]],[[6,7,7]],[8],[[1,9],[[11,[10]]]],[[5,9],12],[[]],[[]],[[]],[5,[[13,[4]]]],[[]],[[]],[[]],[[],2],[[],2],[1],[[],1],[[]],[[],14],[[],11],[[],11],[[],11],[[],11],[[],11],[[],11],[8,2],[[],15],[[],15],[[],15],[[],2],[[],2],[[],2],[[],2]],"c":[],"p":[[3,"Gdt"],[4,"Descriptor"],[4,"PrivilegeLevel"],[3,"SegmentSelector"],[4,"AvailableSegmentSelector"],[3,"CpuId"],[3,"VirtualAddress"],[3,"TaskStateSegment"],[3,"Formatter"],[3,"Error"],[4,"Result"],[6,"Result"],[4,"Option"],[3,"String"],[3,"TypeId"]]},\
+"generic_timer_aarch64":{"doc":"Support for aarch64’s generic timer and system counter.","t":"","n":[],"q":[],"d":[],"i":[],"f":[],"c":[],"p":[]},\
"gic":{"doc":"Arm Generic Interrupt Controller Support","t":"","n":[],"q":[],"d":[],"i":[],"f":[],"c":[],"p":[]},\
"heap":{"doc":"The global allocator for the system. It starts off as a …","t":"HRDLLLLLLFLFLLL","n":["GLOBAL_ALLOCATOR","HEAP_FLAGS","Heap","alloc","borrow","borrow_mut","dealloc","empty","from","init_single_heap","into","set_allocator","try_from","try_into","type_id"],"q":[[0,"heap"]],"d":["","The heap mapped pages should be writable and …","The heap which is used as a global allocator for the …","","","","","Returns a heap in which only an empty initial allocator …","Returns the argument unchanged.","Initializes the single heap, which is the first heap used …","Calls U::from(self)
.","Sets a new default allocator to be used by the global …","","",""],"i":[0,0,0,1,1,1,1,1,1,0,1,0,1,1,1],"f":[0,0,0,[[1,2],3],[[]],[[]],[[1,3,2]],[[],1],[[]],[[4,4]],[[]],[[[6,[5]]]],[[],7],[[],7],[[],8]],"c":[],"p":[[3,"Heap"],[3,"Layout"],[15,"u8"],[15,"usize"],[8,"GlobalAlloc"],[3,"Box"],[4,"Result"],[3,"TypeId"]]},\
"heapfile":{"doc":"An implementation of in-memory files, backed by heap …","t":"DLLLLLLLLLLLLLLLLL","n":["HeapFile","as_mapping","borrow","borrow_mut","create","flush","from","from_vec","get_name","get_parent_dir","into","len","read_at","set_parent_dir","try_from","try_into","type_id","write_at"],"q":[[0,"heapfile"]],"d":["A file in memory that is backed by the heap, i.e., a Vec
.","","","","Creates a new file with empty content in the given parent
…","","Returns the argument unchanged.","Creates a new HeapFile
in the given parent
directory with …","","","Calls U::from(self)
.","","","","","","",""],"i":[0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1],"f":[0,[1,[[4,[2,3]]]],[[]],[[]],[[5,6],[[4,[7,3]]]],[1,[[4,[8]]]],[[]],[[[10,[9]],5,6],[[4,[7,3]]]],[1,5],[1,[[11,[6]]]],[[]],[1,12],[[1,[13,[9]],12],[[4,[12,8]]]],[[1,14]],[[],4],[[],4],[[],15],[[1,[13,[9]],12],[[4,[12,8]]]]],"c":[],"p":[[3,"HeapFile"],[3,"MappedPages"],[15,"str"],[4,"Result"],[3,"String"],[6,"DirRef"],[6,"FileRef"],[4,"IoError"],[15,"u8"],[3,"Vec"],[4,"Option"],[15,"usize"],[15,"slice"],[6,"WeakDirRef"],[3,"TypeId"]]},\
diff --git a/doc/sleep/fn.sleep.html b/doc/sleep/fn.sleep.html
index 348a17c25f..4e0e155a11 100644
--- a/doc/sleep/fn.sleep.html
+++ b/doc/sleep/fn.sleep.html
@@ -1,3 +1,3 @@
-
sleep in sleep - Rust pub fn sleep(duration: Duration) -> Result<(), RunState>
Expand description
Blocks the current task by putting it to sleep for duration
ticks.
+sleep in sleep - Rust
\ No newline at end of file
diff --git a/doc/sleep/fn.sleep_until.html b/doc/sleep/fn.sleep_until.html
index 5b57a26cb3..45b2764619 100644
--- a/doc/sleep/fn.sleep_until.html
+++ b/doc/sleep/fn.sleep_until.html
@@ -1,4 +1,4 @@
-sleep_until in sleep - Rust Function sleep::sleep_until
source · pub fn sleep_until(resume_time: Instant) -> Result<(), RunState>
Expand description
Blocks the current task by putting it to sleep until a specific tick count is reached,
+
sleep_until in sleep - Rust Function sleep::sleep_until
source · pub fn sleep_until(resume_time: Instant) -> Result<(), RunState>
Expand description
Blocks the current task by putting it to sleep until a specific tick count is reached,
given by resume_time
.
Returns the current task’s run state if it can’t be blocked.
\ No newline at end of file
diff --git a/doc/sleep/fn.unblock_sleeping_tasks.html b/doc/sleep/fn.unblock_sleeping_tasks.html
index f277ae5811..00b2357839 100644
--- a/doc/sleep/fn.unblock_sleeping_tasks.html
+++ b/doc/sleep/fn.unblock_sleeping_tasks.html
@@ -1,3 +1,2 @@
-unblock_sleeping_tasks in sleep - Rust Function sleep::unblock_sleeping_tasks
source · pub fn unblock_sleeping_tasks()
Expand description
Remove all tasks that have been delayed but are able to be unblocked now,
-the current tick count is provided by the system’s interrupt tick count.
+unblock_sleeping_tasks in sleep - Rust Function sleep::unblock_sleeping_tasks
source · pub fn unblock_sleeping_tasks()
Expand description
Remove all tasks that have been delayed but are able to be unblocked now.
\ No newline at end of file
diff --git a/doc/sleep/future/fn.sleep.html b/doc/sleep/future/fn.sleep.html
index 4ee25e6961..71d2db3a70 100644
--- a/doc/sleep/future/fn.sleep.html
+++ b/doc/sleep/future/fn.sleep.html
@@ -1,2 +1,2 @@
-sleep in sleep::future - Rust pub fn sleep(duration: Duration, waker: Waker)
Expand description
Wakes up the waker after the specified duration.
+sleep in sleep::future - Rust
\ No newline at end of file
diff --git a/doc/sleep/future/fn.sleep_until.html b/doc/sleep/future/fn.sleep_until.html
index 6c40282233..5733b06c96 100644
--- a/doc/sleep/future/fn.sleep_until.html
+++ b/doc/sleep/future/fn.sleep_until.html
@@ -1,2 +1,2 @@
-sleep_until in sleep::future - Rust Function sleep::future::sleep_until
source · pub fn sleep_until(resume_time: Instant, waker: &Waker) -> Poll<()>
Expand description
Wakes up the waker at the specified time.
+sleep_until in sleep::future - Rust
\ No newline at end of file
diff --git a/doc/sleep/future/index.html b/doc/sleep/future/index.html
index 98e807f7b4..4d3473d4b8 100644
--- a/doc/sleep/future/index.html
+++ b/doc/sleep/future/index.html
@@ -1,2 +1,2 @@
-sleep::future - Rust Expand description
Asynchronous sleep methods that operate on wakers.
+sleep::future - Rust
\ No newline at end of file
diff --git a/doc/sleep/index.html b/doc/sleep/index.html
index 89a5a14cbb..33a124be3e 100644
--- a/doc/sleep/index.html
+++ b/doc/sleep/index.html
@@ -1,4 +1,4 @@
-sleep - Rust Expand description
Provides APIs for tasks to sleep for specified time durations.
+sleep - Rust Expand description
Provides APIs for tasks to sleep for specified time durations.
Key functions:
- The
sleep
function delays the current task for a given number of ticks.
@@ -9,5 +9,4 @@
TODO: use regular time-keeping abstractions like Duration and Instant.
Modules
- Asynchronous sleep methods that operate on wakers.
Structs
- A
Duration
type to represent a span of time, typically used for system
timeouts.
Functions
- Blocks the current task by putting it to sleep for
duration
ticks. - Blocks the current task by putting it to sleep until a specific tick count is reached,
-given by
resume_time
. - Remove all tasks that have been delayed but are able to be unblocked now,
-the current tick count is provided by the system’s interrupt tick count.
\ No newline at end of file
+given by resume_time
.Remove all tasks that have been delayed but are able to be unblocked now.
\ No newline at end of file
diff --git a/doc/source-files.js b/doc/source-files.js
index cde169b511..9781c590a3 100644
--- a/doc/source-files.js
+++ b/doc/source-files.js
@@ -61,6 +61,7 @@ var sourcesIndex = JSON.parse('{\
"framebuffer_printer":["",[],["lib.rs"]],\
"fs_node":["",[],["lib.rs"]],\
"gdt":["",[],["lib.rs"]],\
+"generic_timer_aarch64":["",[],["lib.rs"]],\
"gic":["",[],["lib.rs"]],\
"heap":["",[],["lib.rs"]],\
"heapfile":["",[],["lib.rs"]],\
diff --git a/doc/src/captain/lib.rs.html b/doc/src/captain/lib.rs.html
index c9e6eee3f0..b9d0e13ab4 100644
--- a/doc/src/captain/lib.rs.html
+++ b/doc/src/captain/lib.rs.html
@@ -235,6 +235,7 @@
235
236
237
+238
//! The main initialization routine and setup logic of the OS.
//!
//! The `captain` steers the ship of Theseus, meaning that it contains basic logic
@@ -335,6 +336,7 @@
device_manager::early_init(rsdp_address, kernel_mmi_ref.lock().deref_mut())?;
// Initialize local and system-wide interrupt controllers.
+ // TODO: move this into `interrupts::init()`.
interrupt_controller::init(&kernel_mmi_ref)?;
// Initialize other arch-specific interrupt stuff, e.g., basic interrupt handlers.
diff --git a/doc/src/generic_timer_aarch64/lib.rs.html b/doc/src/generic_timer_aarch64/lib.rs.html
new file mode 100644
index 0000000000..655576a895
--- /dev/null
+++ b/doc/src/generic_timer_aarch64/lib.rs.html
@@ -0,0 +1,179 @@
+lib.rs - source 1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+84
+85
+86
+87
+88
+89
+
//! Support for aarch64's generic timer and system counter.
+//!
+//! Docs: <https://developer.arm.com/documentation/102379/latest/>
+
+#![no_std]
+#![feature(negative_impls)]
+
+// This crate is only relevant on aarch64 systems,
+// but we use a cfg gate here to allow it to be included in x86 builds
+// because the build system currently builds _all_ crates for x86.
+#[cfg(target_arch = "aarch64")]
+pub use aarch64::*;
+
+#[cfg(target_arch = "aarch64")]
+mod aarch64 {
+
+use cortex_a::registers::*;
+use log::*;
+use time::{Monotonic, ClockSource, Instant, Period, register_clock_source};
+use tock_registers::interfaces::Writeable;
+use tock_registers::interfaces::Readable;
+
+
+/// Initializes the aarch64 generic system timer
+/// and registers it as a monotonic [`ClockSource`].
+///
+/// This only needs to be invoked once, system-wide.
+/// However, each CPU will need to enable their own timer interrupt separately,
+/// as this function itself does not enable the timer interrupt.
+pub fn init() {
+ let period = Period::new(timer_period_femtoseconds());
+ register_clock_source::<PhysicalSystemCounter>(period);
+}
+
+/// A ClockSource for the time crate, implemented using
+/// the System Counter of the Generic Arm Timer. The
+/// period of this timer is computed in `init` above.
+#[derive(Debug, Copy, Clone, PartialEq, Eq)]
+#[non_exhaustive]
+pub struct PhysicalSystemCounter;
+impl !Send for PhysicalSystemCounter { }
+impl PhysicalSystemCounter {
+ /// An instant (no-op) function that returns the current CPU's system counter.
+ pub fn get() -> Self {
+ Self
+ }
+}
+impl ClockSource for PhysicalSystemCounter {
+ type ClockType = Monotonic;
+
+ fn now() -> Instant {
+ Instant::new(CNTPCT_EL0.get())
+ }
+}
+
+/// Returns the period in femtoseconds of the generic system timer.
+///
+/// This reads the `CNTFRQ_EL0` system register.
+pub fn timer_period_femtoseconds() -> u64 {
+ let counter_freq_hz = CNTFRQ_EL0.get();
+ let fs_in_one_sec = 1_000_000_000_000_000;
+ fs_in_one_sec / counter_freq_hz
+}
+
+/// Sets the current CPU's system timer interrupt to fire after `ticks_to_elapse` from now.
+pub fn set_next_timer_interrupt(ticks_to_elapse: u64) {
+ enable_timer_interrupt(false);
+ CNTP_TVAL_EL0.set(ticks_to_elapse);
+ enable_timer_interrupt(true);
+}
+
+/// Enables/disables the generic system timer interrupt on the current CPU.
+///
+/// This writes the `CNTP_CTL_EL0` system register.
+pub fn enable_timer_interrupt(enable: bool) {
+ // Unmask the interrupt (to enable it), and enable the timer.
+ CNTP_CTL_EL0.write(
+ CNTP_CTL_EL0::IMASK.val(!enable as u64)
+ + CNTP_CTL_EL0::ENABLE.val(enable as u64)
+ );
+
+ if false {
+ info!("timer enabled: {:?}", CNTP_CTL_EL0.read(CNTP_CTL_EL0::ENABLE));
+ info!("timer IMASK: {:?}", CNTP_CTL_EL0.read(CNTP_CTL_EL0::IMASK));
+ info!("timer status: {:?}", CNTP_CTL_EL0.read(CNTP_CTL_EL0::ISTATUS));
+ }
+}
+
+}
+
\ No newline at end of file
diff --git a/doc/src/interrupts/x86_64/mod.rs.html b/doc/src/interrupts/x86_64/mod.rs.html
index 93ebe5f605..dad980535c 100644
--- a/doc/src/interrupts/x86_64/mod.rs.html
+++ b/doc/src/interrupts/x86_64/mod.rs.html
@@ -382,8 +382,6 @@
382
383
384
-385
-386
pub use pic::IRQ_BASE_OFFSET;
// use rtc;
@@ -693,8 +691,7 @@
extern "x86-interrupt" fn apic_spurious_interrupt_handler(_stack_frame: InterruptStackFrame) {
warn!("APIC SPURIOUS INTERRUPT HANDLER!");
-
- eoi(None);
+ eoi(Some(apic::APIC_SPURIOUS_INTERRUPT_IRQ));
}
extern "x86-interrupt" fn unimplemented_interrupt_handler(_stack_frame: InterruptStackFrame) {
@@ -721,8 +718,7 @@
}
};
- // TODO: use const generics here to know which IRQ to send an EOI for (only needed for PIC).
- eoi(None);
+ eoi(Some(0xFF));
}
diff --git a/doc/src/scheduler/lib.rs.html b/doc/src/scheduler/lib.rs.html
index cb817b53e4..9774560c6d 100644
--- a/doc/src/scheduler/lib.rs.html
+++ b/doc/src/scheduler/lib.rs.html
@@ -78,6 +78,21 @@
78
79
80
+81
+82
+83
+84
+85
+86
+87
+88
+89
+90
+91
+92
+93
+94
+95
//! Offers the ability to control or configure the active task scheduling policy.
//!
//! ## What is and isn't in this crate?
@@ -121,8 +136,8 @@
}
#[cfg(target_arch = "aarch64")] {
- interrupts::init_timer(timer_tick_handler)?;
- interrupts::enable_timer(true);
+ interrupts::setup_timer_interrupt(timer_tick_handler)?;
+ generic_timer_aarch64::enable_timer_interrupt(true);
Ok(())
}
}
@@ -130,7 +145,7 @@
// Architecture-independent timer interrupt handler for preemptive scheduling.
interrupt_handler!(timer_tick_handler, None, _stack_frame, {
#[cfg(target_arch = "aarch64")]
- interrupts::schedule_next_timer_tick();
+ generic_timer_aarch64::set_next_timer_interrupt(get_timeslice_ticks());
// tick count, only used for debugging
if false {
@@ -144,18 +159,33 @@
// in order to unblock any tasks that are done sleeping.
sleep::unblock_sleeping_tasks();
- // We must acknowledge the interrupt before the end of this handler
+ // We must acknowledge the interrupt *before* the end of this handler
// because we switch tasks here, which doesn't return.
- {
- #[cfg(target_arch = "x86_64")]
- eoi(None); // None, because IRQ 0x22 cannot possibly be a PIC interrupt
-
- #[cfg(target_arch = "aarch64")]
- eoi(CPU_LOCAL_TIMER_IRQ);
- }
+ #[cfg(target_arch = "x86_64")]
+ eoi(Some(CPU_LOCAL_TIMER_IRQ));
+ #[cfg(target_arch = "aarch64")]
+ eoi(CPU_LOCAL_TIMER_IRQ);
schedule();
EoiBehaviour::HandlerSentEoi
});
+
+
+/// Returns the (cached) number of system timer ticks needed for the scheduling timeslice interval.
+///
+/// This is only needed on aarch64 because it only effectively offers a one-shot timer;
+/// x86_64 can be configured once as a recurring periodic timer.
+#[cfg(target_arch = "aarch64")]
+fn get_timeslice_ticks() -> u64 {
+ use kernel_config::time::CONFIG_TIMESLICE_PERIOD_MICROSECONDS;
+
+ static TIMESLICE_TICKS: spin::Once<u64> = spin::Once::new();
+
+ *TIMESLICE_TICKS.call_once(|| {
+ let timeslice_femtosecs = (CONFIG_TIMESLICE_PERIOD_MICROSECONDS as u64) * 1_000_000_000;
+ let tick_period_femtosecs = generic_timer_aarch64::timer_period_femtoseconds();
+ timeslice_femtosecs / tick_period_femtosecs
+ })
+}
\ No newline at end of file
diff --git a/doc/src/sleep/lib.rs.html b/doc/src/sleep/lib.rs.html
index 6007fa52db..f59ced6663 100644
--- a/doc/src/sleep/lib.rs.html
+++ b/doc/src/sleep/lib.rs.html
@@ -177,7 +177,6 @@
177
178
179
-180
//! Provides APIs for tasks to sleep for specified time durations.
//!
//! Key functions:
@@ -290,8 +289,7 @@
}
}
-/// Remove all tasks that have been delayed but are able to be unblocked now,
-/// the current tick count is provided by the system's interrupt tick count.
+/// Remove all tasks that have been delayed but are able to be unblocked now.
pub fn unblock_sleeping_tasks() {
let time = now::<Monotonic>();
while time > NEXT_DELAYED_TASK_UNBLOCK_TIME.load() {