ccp_msr/linux_x86_64/
msr_x86_64.rs1use ccp_shared::types::LogicalCoreId;
18
19use super::msr_mode::MSRMode;
20use super::utils;
21use crate::state::MSRCpuPreset;
22use crate::state::MSRPresetItem;
23use crate::MSREnforce;
24use crate::MSRResult;
25
26const DEFAULT_CORE_TO_READ_MSR: LogicalCoreId = LogicalCoreId::new(0);
27
28#[derive(Clone, Debug)]
29pub struct MSRModeEnforcer {
30 is_enabled: bool,
31 original_preset: MSRCpuPreset,
32}
33
34impl MSRModeEnforcer {
35 pub fn from_os(is_enabled: bool) -> Self {
38 if !is_enabled {
39 return Self {
40 is_enabled,
41 original_preset: <_>::default(),
42 };
43 }
44
45 let mode = MSRMode::detect();
46 let preset = mode.get_optimal_cpu_preset();
47
48 let original_items = preset
49 .items()
50 .filter_map(|item| {
51 let register_id = item.register_id();
52 let value = utils::read_msr(register_id, DEFAULT_CORE_TO_READ_MSR).ok()?;
53 Some(MSRPresetItem::new(register_id, value))
54 })
55 .collect();
56 let original_preset = MSRCpuPreset::new(original_items);
57
58 Self {
59 is_enabled,
60 original_preset,
61 }
62 }
63
64 pub fn from_preset(is_enabled: bool, original_preset: MSRCpuPreset) -> Self {
65 Self {
66 is_enabled,
67 original_preset,
68 }
69 }
70
71 pub fn original_preset(&self) -> &MSRCpuPreset {
72 &self.original_preset
73 }
74}
75
76impl MSREnforce for MSRModeEnforcer {
77 fn enforce(&mut self, core_id: LogicalCoreId) -> MSRResult<()> {
78 use super::msr_mode::MSR_MODE;
79
80 if !self.is_enabled {
81 return Ok(());
82 }
83
84 let mode = *MSR_MODE;
85 tracing::debug!("Global MSR mode: mode:{:?}.", mode);
86
87 let preset = mode.get_optimal_cpu_preset();
88 for item in preset.items() {
89 write(*item, core_id)?;
91 }
92
93 Ok(())
94 }
95
96 fn cease(&self, core_id: LogicalCoreId) -> MSRResult<()> {
97 if !self.is_enabled {
98 return Ok(());
99 }
100
101 for item in self.original_preset.items() {
102 write(*item, core_id)?;
103 }
104 Ok(())
105 }
106}
107
108pub fn write(item: MSRPresetItem, core_id: LogicalCoreId) -> MSRResult<()> {
109 let value_to_write = if item.mask() != MSRPresetItem::NO_MASK {
110 let old_value = utils::read_msr(item.register_id(), core_id)?;
111 MSRPresetItem::masked_value(old_value, item.value(), item.mask())
112 } else {
113 item.value()
114 };
115
116 tracing::debug!(
117 "Write MSR register_id {} value {:#X} at logical CPU {} ",
118 item.register_id(),
119 value_to_write,
120 core_id
121 );
122 utils::write_msr(item.register_id(), value_to_write, core_id)
123}