Skip to content

Commit 8795545

Browse files
committed
Start creating abstractions for APIC registers
1 parent 4bbceb0 commit 8795545

File tree

4 files changed

+177
-7
lines changed

4 files changed

+177
-7
lines changed

Cargo.toml

+2-2
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,6 @@ version = "0.1.0"
44
authors = ["Philipp Oppermann <dev@phil-opp.com>"]
55
edition = "2018"
66

7-
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
8-
97
[dependencies]
8+
bit_field = "0.10.1"
9+
volatile = "0.4.0-alpha"

rust-toolchain

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
nightly

src/lib.rs

+83-5
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,85 @@
1-
#[cfg(test)]
2-
mod tests {
3-
#[test]
4-
fn it_works() {
5-
assert_eq!(2 + 2, 4);
1+
#![no_std]
2+
#![feature(unsafe_block_in_unsafe_fn)]
3+
#![deny(unsafe_op_in_unsafe_fn)]
4+
5+
use volatile::Volatile;
6+
7+
pub mod registers;
8+
9+
pub struct ApicRegisters {
10+
base_addr: *mut (),
11+
}
12+
13+
impl ApicRegisters {
14+
pub fn id(&mut self) -> Volatile<&mut registers::Id> {
15+
unsafe { self.offset(Offset::Id) }
16+
}
17+
18+
pub fn version(&mut self) -> Volatile<&mut registers::Version> {
19+
unsafe { self.offset(Offset::Version) }
20+
}
21+
22+
pub fn extended_apic_feature(&mut self) -> Volatile<&mut registers::ExtendedApicFeature> {
23+
unsafe { self.offset(Offset::ExtendedApicFeature) }
624
}
25+
26+
pub fn extended_apic_control(&mut self) -> Volatile<&mut registers::ExtendedApicControl> {
27+
unsafe { self.offset(Offset::ExtendedApicControl) }
28+
}
29+
30+
/*
31+
pub fn task_priority(&mut self) -> Volatile<&mut registers::TaskPriority> {
32+
unsafe { self.offset(Offset::TaskPriority) }
33+
}
34+
35+
pub fn arbitration_priority(&mut self) -> Volatile<&mut registers::ArbitrationPriority> {
36+
unsafe { self.offset(Offset::ArbitrationPriority) }
37+
}
38+
39+
pub fn processor_priority(&mut self) -> Volatile<&mut registers::ProcessorPriority> {
40+
unsafe { self.offset(Offset::ProcessorPriority) }
41+
}
42+
43+
pub fn end_of_interrupt(&mut self) -> Volatile<&mut registers::EndOfInterrupt> {
44+
unsafe { self.offset(Offset::EndOfInterrupt) }
45+
}
46+
*/
47+
48+
unsafe fn offset<T>(&mut self, offset: Offset) -> Volatile<&mut T> {
49+
let ptr = self.base_addr.wrapping_add(offset as usize).cast();
50+
Volatile::new(unsafe { &mut *ptr })
51+
}
52+
}
53+
54+
#[repr(usize)]
55+
pub enum Offset {
56+
Id = 0x20,
57+
Version = 0x30,
58+
TaskPriority = 0x80,
59+
ArbitrationPriority = 0x90,
60+
ProcessorPriority = 0xa0,
61+
EndOfInterrupt = 0xb0,
62+
RemoteRead = 0xc0,
63+
LocalDestination = 0xd0,
64+
DestinationFormat = 0xe0,
65+
SpuriousInterruptVector = 0xf0,
66+
InService = 0x100,
67+
TriggerMode = 0x180,
68+
InterruptRequest = 0x200,
69+
ErrorStatus = 0x280,
70+
InterruptCommand = 0x300,
71+
TimerLocalVectorTableEntry = 0x320,
72+
ThermalLocalVectorTableEntry = 0x330,
73+
PerformanceCounterLocalVectorTableEntry = 0x340,
74+
LocalInterrupt0VectorTableEntry = 0x350,
75+
LocalInterrupt1VectorTableEntry = 0x360,
76+
ErrorVectorTableEntry = 0x370,
77+
TimerInitialCount = 0x380,
78+
TimerCurrentCount = 0x390,
79+
TimerDivideConfiguration = 0x3e0,
80+
ExtendedApicFeature = 0x400,
81+
ExtendedApicControl = 0x410,
82+
SpecificEndOfInterrupt = 0x420,
83+
InterruptEnable = 0x480,
84+
ExtendedInterruptLocalVectorTable = 0x500,
785
}

src/registers.rs

+91
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
use core::convert::TryInto;
2+
3+
use bit_field::BitField;
4+
5+
#[derive(Debug, Copy, Clone)]
6+
#[repr(transparent)]
7+
pub struct Id(u32);
8+
9+
impl Id {
10+
/// Returns the unique APIC ID value assigned to this specific CPU core
11+
pub fn id(&self) -> u8 {
12+
self.0.get_bits(24..).try_into().unwrap()
13+
}
14+
}
15+
16+
#[derive(Debug, Copy, Clone)]
17+
#[repr(transparent)]
18+
pub struct Version(u32);
19+
20+
impl Version {
21+
/// Indicates the version number of the APIC implementation
22+
pub fn version(&self) -> u8 {
23+
self.0.get_bits(..8).try_into().unwrap()
24+
}
25+
26+
/// Specifies the number of entries in the localvector table minus one
27+
pub fn max_lvt_entries(&self) -> u8 {
28+
self.0.get_bits(16..24).try_into().unwrap()
29+
}
30+
31+
/// Indicates thepresence of an extended APIC register space
32+
pub fn extended_apic_register_space_present(&self) -> bool {
33+
self.0.get_bit(31)
34+
}
35+
}
36+
37+
#[derive(Debug, Copy, Clone)]
38+
#[repr(transparent)]
39+
pub struct ExtendedApicFeature(u32);
40+
41+
impl ExtendedApicFeature {
42+
/// Specifies the number of extended local vector tableregisters in the local APIC
43+
pub fn extended_lvt_count(&self) -> u8 {
44+
self.0.get_bits(16..24).try_into().unwrap()
45+
}
46+
47+
/// Indicates that the processor is capable ofsupporting an 8-bit APIC ID
48+
pub fn extended_apic_id_capability(&self) -> bool {
49+
self.0.get_bit(2)
50+
}
51+
52+
/// Indicates that the Specific End Of Interrupt Register is present
53+
pub fn specific_end_of_interrupt_capable(&self) -> bool {
54+
self.0.get_bit(1)
55+
}
56+
57+
/// Indicates that the Interrupt EnableRegisters are present
58+
pub fn interrupt_enable_register_capable(&self) -> bool {
59+
self.0.get_bit(1)
60+
}
61+
}
62+
63+
#[derive(Debug, Copy, Clone)]
64+
#[repr(transparent)]
65+
pub struct ExtendedApicControl(u32);
66+
67+
impl ExtendedApicControl {
68+
pub fn extended_apic_id_enabled(&self) -> bool {
69+
self.0.get_bit(2)
70+
}
71+
72+
pub fn enable_extended_apic_id(&mut self, enable: bool) {
73+
self.0.set_bit(2, enable);
74+
}
75+
76+
pub fn specific_end_of_interrupt_generation_enabled(&self) -> bool {
77+
self.0.get_bit(1)
78+
}
79+
80+
pub fn enable_specific_end_of_interrupt_generation(&mut self, enable: bool) {
81+
self.0.set_bit(1, enable);
82+
}
83+
84+
pub fn interrupt_enable_registers_enabled(&self) -> bool {
85+
self.0.get_bit(0)
86+
}
87+
88+
pub fn enable_interrupt_enable_registers(&mut self, enable: bool) {
89+
self.0.set_bit(0, enable);
90+
}
91+
}

0 commit comments

Comments
 (0)