1use crate::{Accessible, IoHandle, LayoutOver, Register, Ro, RwSafe, RwUnsafe};
6
7pub trait ControlRegister {
9 type Access: Accessible;
10}
11
12impl ControlRegister for CrIo<0> {
13 type Access = RwUnsafe;
15}
16
17impl ControlRegister for CrIo<2> {
18 type Access = Ro;
19}
20
21impl ControlRegister for CrIo<3> {
22 type Access = RwUnsafe;
24}
25
26impl ControlRegister for CrIo<4> {
27 type Access = RwUnsafe;
29}
30
31impl ControlRegister for CrIo<8> {
32 type Access = RwSafe;
33}
34
35impl ControlRegister for XcrIo<0> {
36 type Access = RwSafe;
37}
38
39pub type Cr<const N: u32, Layout> = Register<Layout, <CrIo<N> as ControlRegister>::Access, CrIo<N>>;
46
47impl<const N: u32, Layout> Cr<N, Layout>
48where
49 CrIo<N>: ControlRegister,
50 Layout: LayoutOver<u64>,
51{
52 pub const fn new() -> Self {
54 unsafe { Self::from_io(CrIo {}) }
56 }
57}
58
59pub type Xcr<const N: u32, Layout> =
66 Register<Layout, <XcrIo<N> as ControlRegister>::Access, XcrIo<N>>;
67
68impl<const N: u32, Layout> Xcr<N, Layout>
69where
70 XcrIo<N>: ControlRegister,
71 Layout: LayoutOver<u64>,
72{
73 pub const fn new() -> Self {
75 unsafe { Self::from_io(XcrIo {}) }
77 }
78}
79
80pub struct CrIo<const N: u32> {}
82
83impl<const N: u32> IoHandle for CrIo<N> {
84 type Base = u64;
85}
86
87pub struct XcrIo<const N: u32> {}
89
90impl<const N: u32> IoHandle for XcrIo<N> {
91 type Base = u64;
92}
93
94#[cfg(target_arch = "x86_64")]
95mod x86_64_only {
96 use core::arch::asm;
97
98 use super::*;
99 use crate::{ReadHandle, WriteHandle};
100
101 macro_rules! impl_cr_io {
102 ($n:literal, $cr_str:literal) => {
103 impl ReadHandle for CrIo<$n> {
104 #[inline]
105 unsafe fn read_raw(&self) -> u64 {
106 let value: u64;
107 unsafe {
108 asm!(
109 concat!("mov {value}, ", $cr_str),
110 value = out(reg) value,
111 options(nomem, nostack, preserves_flags),
112 );
113 }
114 value
115 }
116 }
117
118 impl WriteHandle for CrIo<$n> {
119 #[inline]
120 unsafe fn write_raw(&self, value: u64) {
121 unsafe {
122 asm!(
123 concat!("mov ", $cr_str, ", {value}"),
124 value = in(reg) value,
125 options(nostack, preserves_flags),
127 );
128 }
129 }
130 }
131 };
132 }
133
134 impl_cr_io!(0, "cr0");
135 impl_cr_io!(2, "cr2");
136 impl_cr_io!(3, "cr3");
137 impl_cr_io!(4, "cr4");
138 impl_cr_io!(8, "cr8");
139}
140
141#[cfg(all(target_arch = "x86_64", feature = "xsave"))]
142mod x86_64_xsave_only {
143 use core::arch::x86::{_xgetbv, _xsetbv};
144
145 use super::*;
146 use crate::{ReadHandle, WriteHandle};
147
148 macro_rules! impl_xcr_io {
149 ($n:literal) => {
150 impl ReadHandle for XcrIo<$n> {
151 #[inline]
152 unsafe fn read_raw(&self) -> u64 {
153 unsafe { _xgetbv($n) }
154 }
155 }
156
157 impl WriteHandle for XcrIo<$n> {
158 #[inline]
159 unsafe fn write_raw(&self, value: u64) {
160 unsafe { _xsetbv($n, value) }
161 }
162 }
163 };
164 }
165 impl_xcr_io!(0);
166}
167
168#[cfg(all(test, target_arch = "x86_64"))]
169mod tests {
170 use super::*;
171
172 #[test]
173 fn test_cr_compilation() {
174 #[allow(unused)]
175 {
176 const CR0: Cr<0, u64> = Cr::new();
177 const CR2: Cr<2, u64> = Cr::new();
178 const CR3: Cr<3, u64> = Cr::new();
179 const CR4: Cr<4, u64> = Cr::new();
180 const CR8: Cr<8, u64> = Cr::new();
181 }
182 }
183}