1use core::{arch::asm, convert::Infallible, fmt, mem};
2use mycelium_util::bits;
3
4pub mod entropy;
5pub mod intrinsics;
6#[cfg(feature = "alloc")]
7pub mod local;
8pub mod msr;
9pub use self::msr::Msr;
10
11#[repr(transparent)]
12pub struct Port {
13 num: u16,
14}
15
16#[derive(Copy, Clone, Debug, Eq, PartialEq)]
22pub enum DescriptorTable {
23 Gdt,
28
29 Ldt,
34
35 Idt,
40}
41
42#[derive(Copy, Clone, Debug, Eq, PartialEq)]
43#[repr(u8)]
44pub enum Ring {
45 Ring0 = 0b00,
46 Ring1 = 0b01,
47 Ring2 = 0b10,
48 Ring3 = 0b11,
49}
50
51#[repr(C, packed)]
52pub(crate) struct DtablePtr {
53 limit: u16,
54 base: *const (),
55}
56
57#[derive(Copy, Clone, Debug, Eq, PartialEq)]
60pub struct FeatureNotSupported(&'static str);
61
62#[inline(always)]
71pub fn halt() -> ! {
72 unsafe {
73 intrinsics::cli();
75 loop {
76 intrinsics::hlt();
77 }
78 }
79}
80
81#[inline(always)]
91pub fn wait_for_interrupt() {
92 unsafe {
93 intrinsics::sti();
94 intrinsics::hlt();
95 }
96}
97
98impl fmt::Debug for Port {
101 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
102 let Self { num } = self;
103 f.debug_struct("Port")
104 .field("num", &format_args!("{num:#02x}"))
105 .finish()
106 }
107}
108
109impl Port {
110 pub const fn at(address: u16) -> Self {
111 Port { num: address }
112 }
113
114 pub unsafe fn readb(&self) -> u8 {
118 let result: u8;
119 asm!("in al, dx", in("dx") self.num, out("al") result);
120 result
121 }
122
123 pub unsafe fn writeb(&self, value: u8) {
127 asm!("out dx, al", in("dx") self.num, in("al") value)
128 }
129
130 pub unsafe fn readl(&self) -> u32 {
134 let result: u32;
135 asm!("in eax, dx", in("dx") self.num, out("eax") result);
136 result
137 }
138
139 pub unsafe fn writel(&self, value: u32) {
143 asm!("out dx, eax", in("dx") self.num, in("eax") value)
144 }
145}
146
147impl fmt::Display for DescriptorTable {
150 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
151 match self {
152 Self::Gdt => f.pad("GDT"),
153 Self::Ldt => f.pad("LDT"),
154 Self::Idt => f.pad("IDT"),
155 }
156 }
157}
158
159impl bits::FromBits<u16> for DescriptorTable {
160 type Error = Infallible;
161 const BITS: u32 = 2;
162 fn try_from_bits(bits: u16) -> Result<Self, Self::Error> {
163 Ok(match bits {
164 0b00 => Self::Gdt,
165 0b01 => Self::Idt,
166 0b10 => Self::Ldt,
167 0b11 => Self::Idt,
168 _ => unreachable!("only 2 bits should be unpacked!"),
169 })
170 }
171
172 fn into_bits(self) -> u16 {
173 todo!("eliza")
174 }
175}
176
177impl Ring {
180 pub fn from_u8(u: u8) -> Self {
181 match u {
182 0b00 => Ring::Ring0,
183 0b01 => Ring::Ring1,
184 0b10 => Ring::Ring2,
185 0b11 => Ring::Ring3,
186 bits => panic!("invalid ring {bits:#02b}"),
187 }
188 }
189}
190
191impl bits::FromBits<u64> for Ring {
192 const BITS: u32 = 2;
193 type Error = core::convert::Infallible;
194
195 fn try_from_bits(u: u64) -> Result<Self, Self::Error> {
196 Ok(Self::from_u8(u as u8))
197 }
198
199 fn into_bits(self) -> u64 {
200 self as u8 as u64
201 }
202}
203
204impl bits::FromBits<u16> for Ring {
205 const BITS: u32 = 2;
206 type Error = core::convert::Infallible;
207
208 fn try_from_bits(u: u16) -> Result<Self, Self::Error> {
209 Ok(Self::from_u8(u as u8))
210 }
211
212 fn into_bits(self) -> u16 {
213 self as u8 as u16
214 }
215}
216
217impl bits::FromBits<u8> for Ring {
218 const BITS: u32 = 2;
219 type Error = core::convert::Infallible;
220
221 fn try_from_bits(u: u8) -> Result<Self, Self::Error> {
222 Ok(Self::from_u8(u))
223 }
224
225 fn into_bits(self) -> u8 {
226 self as u8
227 }
228}
229
230impl DtablePtr {
233 pub(crate) fn new<T>(t: &'static T) -> Self {
234 unsafe {
235 Self::new_unchecked(t)
238 }
239 }
240
241 pub(crate) unsafe fn new_unchecked<T>(t: &T) -> Self {
242 let limit = (mem::size_of::<T>() - 1) as u16;
243 let base = t as *const _ as *const ();
244
245 Self { limit, base }
246 }
247}
248
249impl fmt::Debug for DtablePtr {
250 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
251 let Self { limit, base } = *self;
254 f.debug_struct("DtablePtr")
255 .field("base", &format_args!("{base:0p}",))
256 .field("limit", &limit)
257 .finish()
258 }
259}
260
261impl fmt::Display for FeatureNotSupported {
264 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
265 write!(f, "this CPU does not support {}", self.0)
266 }
267}
268
269impl FeatureNotSupported {
270 pub fn feature_name(&self) -> &'static str {
271 self.0
272 }
273
274 pub(crate) fn new(feature_name: &'static str) -> Self {
275 Self(feature_name)
276 }
277}