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