1use crate::{Accessible, IoHandle, LayoutOver, Register};
6
7pub type Msr<const ID: u32, Layout, Access> = Register<Layout, Access, MsrIo<ID>>;
15
16impl<const ID: u32, Layout, Access> Msr<ID, Layout, Access>
17where
18 Layout: LayoutOver<u64>,
19 Access: Accessible,
20{
21 pub const fn new() -> Self {
23 unsafe { Self::from_io(MsrIo {}) }
25 }
26}
27
28pub struct MsrIo<const ID: u32> {}
30
31impl<const ID: u32> IoHandle for MsrIo<ID> {
32 type Base = u64;
33}
34
35#[cfg(target_arch = "x86_64")]
36mod x86_64_only {
37 use super::*;
38 use crate::{ReadHandle, WriteHandle};
39
40 use core::arch::asm;
41
42 impl<const ID: u32> ReadHandle for MsrIo<ID> {
43 #[inline]
44 unsafe fn read_raw(&self) -> u64 {
45 let hi: u32;
46 let lo: u32;
47 unsafe {
48 asm!(
49 "rdmsr",
50 in("ecx") ID,
51 out("eax") lo,
52 out("edx") hi,
53 options(nomem, nostack, preserves_flags),
54 )
55 };
56 u64::from(hi) << 32 | u64::from(lo)
57 }
58 }
59
60 impl<const ID: u32> WriteHandle for MsrIo<ID> {
61 #[inline]
62 unsafe fn write_raw(&self, value: u64) {
63 let hi = (value >> 32) as u32;
64 let lo = value as u32;
65 unsafe {
66 asm!(
67 "wrmsr",
68 in("ecx") ID,
69 in("eax") lo,
70 in("edx") hi,
71 options(nomem, nostack, preserves_flags),
72 )
73 }
74 }
75 }
76}
77
78#[cfg(all(test, target_arch = "x86_64"))]
79mod tests {
80 use super::*;
81 use crate::RwSafe;
82
83 #[test]
87 fn test_msr_compilation() {
88 #[allow(unused)]
89 const IA32_TIME_STAMP_COUNTER: Msr<0x10, u64, RwSafe> = Msr::new();
90 }
91}