Skip to content

Commit fdfb47e

Browse files
committed
Constify AddrFilters
1 parent d586966 commit fdfb47e

File tree

3 files changed

+140
-75
lines changed

3 files changed

+140
-75
lines changed

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "libipt"
3-
version = "0.3.1"
3+
version = "0.4.0"
44
authors = [
55
"sum_catnip <[email protected]>",
66
"Marcondiro <[email protected]>",

src/enc_dec_builder/filter.rs

Lines changed: 132 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,28 @@
1+
use crate::error::{PtError, PtErrorCode};
12
use libipt_sys::pt_conf_addr_filter;
23
use num_enum::TryFromPrimitive;
3-
use std::convert::TryFrom;
4-
use std::mem;
4+
use std::mem::{transmute, zeroed};
55

66
/// This corresponds to the IA32_RTIT_ADDRn_CFG MSRs
7-
#[derive(Clone, Copy, TryFromPrimitive, PartialEq, Debug)]
7+
#[derive(Clone, Copy, TryFromPrimitive, PartialEq, Debug, Default)]
88
#[repr(u32)]
99
pub enum AddrFilterType {
10+
#[default]
1011
DISABLED = 0,
1112
FILTER = 1,
1213
STOP = 2,
1314
}
1415

16+
impl AddrFilterType {
17+
#[must_use]
18+
const fn to_addr_cfg_raw(self, n: u32) -> u64 {
19+
(self as u64) << (4 * n)
20+
}
21+
}
22+
1523
/// an address range inside the address filter
1624
#[derive(Debug, Clone, Copy)]
17-
pub struct AddrFilterRange {
25+
pub struct AddrFilter {
1826
/// This corresponds to the IA32_RTIT_ADDRn_A MSRs
1927
pub from: u64,
2028
/// This corresponds to the IA32_RTIT_ADDRn_B MSRs
@@ -23,7 +31,7 @@ pub struct AddrFilterRange {
2331
pub filter_type: AddrFilterType,
2432
}
2533

26-
impl AddrFilterRange {
34+
impl AddrFilter {
2735
#[inline]
2836
pub const fn new(from: u64, to: u64, filter_type: AddrFilterType) -> Self {
2937
Self {
@@ -37,105 +45,160 @@ impl AddrFilterRange {
3745
/// the address filter configuration
3846
#[derive(Debug, Clone, Copy)]
3947
#[repr(transparent)]
40-
pub struct AddrFilters(pub(super) pt_conf_addr_filter);
48+
pub struct AddrFilters(pub(crate) pt_conf_addr_filter);
49+
4150
impl AddrFilters {
42-
pub const fn builder() -> AddrFiltersBuilder {
43-
AddrFiltersBuilder::new()
51+
pub const fn new(filters: &[AddrFilter]) -> Result<Self, PtError> {
52+
if filters.len() > 4 {
53+
return Err(PtError::new(
54+
PtErrorCode::BadConfig,
55+
"The maximum number of address filters is 4",
56+
));
57+
}
58+
let mut inner = unsafe { zeroed::<pt_conf_addr_filter>() };
59+
// TODO improve this when something better will become const, for example get and the
60+
// bindgen methods on config bitfields
61+
if !filters.is_empty() {
62+
(inner.addr0_a, inner.addr0_b) = (filters[0].from, filters[0].to);
63+
unsafe { inner.config.addr_cfg |= filters[0].filter_type.to_addr_cfg_raw(0) };
64+
}
65+
if filters.len() >= 2 {
66+
(inner.addr1_a, inner.addr1_b) = (filters[1].from, filters[1].to);
67+
unsafe { inner.config.addr_cfg |= filters[1].filter_type.to_addr_cfg_raw(1) };
68+
}
69+
if filters.len() >= 3 {
70+
(inner.addr2_a, inner.addr2_b) = (filters[2].from, filters[2].to);
71+
unsafe { inner.config.addr_cfg |= filters[2].filter_type.to_addr_cfg_raw(2) };
72+
}
73+
if filters.len() == 4 {
74+
(inner.addr3_a, inner.addr3_b) = (filters[3].from, filters[3].to);
75+
unsafe { inner.config.addr_cfg |= filters[3].filter_type.to_addr_cfg_raw(3) };
76+
}
77+
78+
Ok(Self(inner))
4479
}
4580

4681
#[inline]
47-
pub fn addr0(&self) -> AddrFilterRange {
48-
AddrFilterRange {
82+
const fn addrn_filter_type(&self, n: u32) -> AddrFilterType {
83+
unsafe { transmute((self.0.config.addr_cfg as u32 >> (4 * n)) & 0xf) }
84+
}
85+
86+
pub const fn addr0(&self) -> AddrFilter {
87+
AddrFilter {
4988
from: self.0.addr0_a,
5089
to: self.0.addr0_b,
51-
filter_type: AddrFilterType::try_from(unsafe { self.0.config.ctl.addr0_cfg() })
52-
.unwrap(),
90+
filter_type: self.addrn_filter_type(0),
5391
}
5492
}
5593

56-
#[inline]
57-
pub fn addr1(&self) -> AddrFilterRange {
58-
AddrFilterRange {
94+
pub const fn addr1(&self) -> AddrFilter {
95+
AddrFilter {
5996
from: self.0.addr1_a,
6097
to: self.0.addr1_b,
61-
filter_type: AddrFilterType::try_from(unsafe { self.0.config.ctl.addr1_cfg() })
62-
.unwrap(),
98+
filter_type: self.addrn_filter_type(1),
6399
}
64100
}
65101

66-
#[inline]
67-
pub fn addr2(&self) -> AddrFilterRange {
68-
AddrFilterRange {
102+
pub const fn addr2(&self) -> AddrFilter {
103+
AddrFilter {
69104
from: self.0.addr2_a,
70105
to: self.0.addr2_b,
71-
filter_type: AddrFilterType::try_from(unsafe { self.0.config.ctl.addr2_cfg() })
72-
.unwrap(),
106+
filter_type: self.addrn_filter_type(2),
73107
}
74108
}
75109

76-
#[inline]
77-
pub fn addr3(&self) -> AddrFilterRange {
78-
AddrFilterRange {
110+
pub const fn addr3(&self) -> AddrFilter {
111+
AddrFilter {
79112
from: self.0.addr3_a,
80113
to: self.0.addr3_b,
81-
filter_type: AddrFilterType::try_from(unsafe { self.0.config.ctl.addr3_cfg() })
82-
.unwrap(),
114+
filter_type: self.addrn_filter_type(3),
83115
}
84116
}
85-
}
86117

87-
#[derive(Debug)]
88-
#[repr(transparent)]
89-
pub struct AddrFiltersBuilder(pub(super) pt_conf_addr_filter);
90-
impl Default for AddrFiltersBuilder {
91-
fn default() -> Self {
92-
Self::new()
93-
}
94-
}
95-
96-
impl AddrFiltersBuilder {
97-
pub const fn new() -> Self {
98-
unsafe { mem::zeroed() }
99-
}
100-
101-
#[inline]
102-
pub fn addr0(&mut self, range: AddrFilterRange) -> &mut Self {
118+
pub const fn set_addr0(&mut self, range: AddrFilter) {
103119
self.0.addr0_a = range.from;
104120
self.0.addr0_b = range.to;
105-
unsafe { self.0.config.ctl.set_addr0_cfg(range.filter_type as u32) };
106-
107-
self
121+
unsafe { self.0.config.addr_cfg |= range.filter_type.to_addr_cfg_raw(0) };
108122
}
109123

110-
#[inline]
111-
pub fn addr1(&mut self, range: AddrFilterRange) -> &mut Self {
124+
pub const fn set_addr1(&mut self, range: AddrFilter) {
112125
self.0.addr1_a = range.from;
113126
self.0.addr1_b = range.to;
114-
unsafe { self.0.config.ctl.set_addr1_cfg(range.filter_type as u32) };
115-
116-
self
127+
unsafe { self.0.config.addr_cfg |= range.filter_type.to_addr_cfg_raw(1) };
117128
}
118129

119-
#[inline]
120-
pub fn addr2(&mut self, range: AddrFilterRange) -> &mut Self {
130+
pub const fn set_addr2(&mut self, range: AddrFilter) {
121131
self.0.addr2_a = range.from;
122132
self.0.addr2_b = range.to;
123-
unsafe { self.0.config.ctl.set_addr2_cfg(range.filter_type as u32) };
124-
125-
self
133+
unsafe { self.0.config.addr_cfg |= range.filter_type.to_addr_cfg_raw(2) };
126134
}
127135

128136
#[inline]
129-
pub fn addr3(&mut self, range: AddrFilterRange) -> &mut Self {
137+
pub const fn set_addr3(&mut self, range: AddrFilter) {
130138
self.0.addr3_a = range.from;
131139
self.0.addr3_b = range.to;
132-
unsafe { self.0.config.ctl.set_addr3_cfg(range.filter_type as u32) };
140+
unsafe { self.0.config.addr_cfg |= range.filter_type.to_addr_cfg_raw(3) };
141+
}
133142

134-
self
143+
pub const fn iter(&self) -> Iter<'_> {
144+
Iter::new(self)
135145
}
146+
}
147+
148+
impl Default for AddrFilters {
149+
fn default() -> Self {
150+
Self(unsafe { zeroed() })
151+
}
152+
}
153+
154+
impl PartialEq for AddrFilters {
155+
fn eq(&self, other: &Self) -> bool {
156+
(
157+
self.0.addr0_a,
158+
self.0.addr0_b,
159+
self.0.addr1_a,
160+
self.0.addr1_b,
161+
self.0.addr2_a,
162+
self.0.addr2_b,
163+
self.0.addr3_a,
164+
self.0.addr3_b,
165+
) == (
166+
other.0.addr0_a,
167+
other.0.addr0_b,
168+
other.0.addr1_a,
169+
other.0.addr1_b,
170+
other.0.addr2_a,
171+
other.0.addr2_b,
172+
other.0.addr3_a,
173+
other.0.addr3_b,
174+
) && unsafe { self.0.config.addr_cfg == other.0.config.addr_cfg }
175+
}
176+
}
177+
178+
pub struct Iter<'a> {
179+
filters: &'a AddrFilters,
180+
i: usize,
181+
}
182+
183+
impl<'a> Iter<'a> {
184+
const fn new(filters: &'a AddrFilters) -> Self {
185+
Self { filters, i: 0 }
186+
}
187+
}
136188

137-
pub fn build(&self) -> AddrFilters {
138-
AddrFilters(self.0)
189+
impl<'a> Iterator for Iter<'a> {
190+
type Item = AddrFilter;
191+
192+
fn next(&mut self) -> Option<Self::Item> {
193+
let filter = match self.i {
194+
0 => self.filters.addr0(),
195+
1 => self.filters.addr1(),
196+
2 => self.filters.addr2(),
197+
3 => self.filters.addr3(),
198+
_ => return None,
199+
};
200+
self.i += 1;
201+
Some(filter)
139202
}
140203
}
141204

@@ -145,12 +208,13 @@ mod test {
145208

146209
#[test]
147210
fn test_addrfilter() {
148-
let filter = AddrFilters::builder()
149-
.addr0(AddrFilterRange::new(1, 2, AddrFilterType::DISABLED))
150-
.addr1(AddrFilterRange::new(3, 4, AddrFilterType::FILTER))
151-
.addr2(AddrFilterRange::new(5, 6, AddrFilterType::STOP))
152-
.addr3(AddrFilterRange::new(7, 8, AddrFilterType::DISABLED))
153-
.build();
211+
let filter = AddrFilters::new(&[
212+
AddrFilter::new(1, 2, AddrFilterType::DISABLED),
213+
AddrFilter::new(3, 4, AddrFilterType::FILTER),
214+
AddrFilter::new(5, 6, AddrFilterType::STOP),
215+
AddrFilter::new(7, 8, AddrFilterType::DISABLED),
216+
])
217+
.unwrap();
154218

155219
assert_eq!(filter.addr0().from, 1);
156220
assert_eq!(filter.addr0().to, 2);

src/enc_dec_builder/mod.rs

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -313,12 +313,13 @@ mod test {
313313
let mut data = [18u8; 3];
314314
let mut c = EncoderDecoderBuilder::<BlockDecoder>::new()
315315
.filter(
316-
AddrFiltersBuilder::new()
317-
.addr0(AddrFilterRange::new(1, 2, AddrFilterType::STOP))
318-
.addr1(AddrFilterRange::new(3, 4, AddrFilterType::FILTER))
319-
.addr2(AddrFilterRange::new(5, 6, AddrFilterType::DISABLED))
320-
.addr3(AddrFilterRange::new(7, 8, AddrFilterType::STOP))
321-
.build(),
316+
AddrFilters::new(&[
317+
AddrFilter::new(1, 2, AddrFilterType::STOP),
318+
AddrFilter::new(3, 4, AddrFilterType::FILTER),
319+
AddrFilter::new(5, 6, AddrFilterType::DISABLED),
320+
AddrFilter::new(7, 8, AddrFilterType::STOP),
321+
])
322+
.unwrap(),
322323
)
323324
.cpu(Cpu::intel(1, 2, 3))
324325
.freq(Frequency::new(1, 2, 3, 4))

0 commit comments

Comments
 (0)