1
+ use crate :: error:: { PtError , PtErrorCode } ;
1
2
use libipt_sys:: pt_conf_addr_filter;
2
3
use num_enum:: TryFromPrimitive ;
3
- use std:: convert:: TryFrom ;
4
- use std:: mem;
4
+ use std:: mem:: { transmute, zeroed} ;
5
5
6
6
/// This corresponds to the IA32_RTIT_ADDRn_CFG MSRs
7
- #[ derive( Clone , Copy , TryFromPrimitive , PartialEq , Debug ) ]
7
+ #[ derive( Clone , Copy , TryFromPrimitive , PartialEq , Debug , Default ) ]
8
8
#[ repr( u32 ) ]
9
9
pub enum AddrFilterType {
10
+ #[ default]
10
11
DISABLED = 0 ,
11
12
FILTER = 1 ,
12
13
STOP = 2 ,
13
14
}
14
15
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
+
15
23
/// an address range inside the address filter
16
24
#[ derive( Debug , Clone , Copy ) ]
17
- pub struct AddrFilterRange {
25
+ pub struct AddrFilter {
18
26
/// This corresponds to the IA32_RTIT_ADDRn_A MSRs
19
27
pub from : u64 ,
20
28
/// This corresponds to the IA32_RTIT_ADDRn_B MSRs
@@ -23,7 +31,7 @@ pub struct AddrFilterRange {
23
31
pub filter_type : AddrFilterType ,
24
32
}
25
33
26
- impl AddrFilterRange {
34
+ impl AddrFilter {
27
35
#[ inline]
28
36
pub const fn new ( from : u64 , to : u64 , filter_type : AddrFilterType ) -> Self {
29
37
Self {
@@ -37,105 +45,160 @@ impl AddrFilterRange {
37
45
/// the address filter configuration
38
46
#[ derive( Debug , Clone , Copy ) ]
39
47
#[ repr( transparent) ]
40
- pub struct AddrFilters ( pub ( super ) pt_conf_addr_filter ) ;
48
+ pub struct AddrFilters ( pub ( crate ) pt_conf_addr_filter ) ;
49
+
41
50
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) )
44
79
}
45
80
46
81
#[ 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 {
49
88
from : self . 0 . addr0_a ,
50
89
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 ) ,
53
91
}
54
92
}
55
93
56
- #[ inline]
57
- pub fn addr1 ( & self ) -> AddrFilterRange {
58
- AddrFilterRange {
94
+ pub const fn addr1 ( & self ) -> AddrFilter {
95
+ AddrFilter {
59
96
from : self . 0 . addr1_a ,
60
97
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 ) ,
63
99
}
64
100
}
65
101
66
- #[ inline]
67
- pub fn addr2 ( & self ) -> AddrFilterRange {
68
- AddrFilterRange {
102
+ pub const fn addr2 ( & self ) -> AddrFilter {
103
+ AddrFilter {
69
104
from : self . 0 . addr2_a ,
70
105
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 ) ,
73
107
}
74
108
}
75
109
76
- #[ inline]
77
- pub fn addr3 ( & self ) -> AddrFilterRange {
78
- AddrFilterRange {
110
+ pub const fn addr3 ( & self ) -> AddrFilter {
111
+ AddrFilter {
79
112
from : self . 0 . addr3_a ,
80
113
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 ) ,
83
115
}
84
116
}
85
- }
86
117
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 ) {
103
119
self . 0 . addr0_a = range. from ;
104
120
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 ) } ;
108
122
}
109
123
110
- #[ inline]
111
- pub fn addr1 ( & mut self , range : AddrFilterRange ) -> & mut Self {
124
+ pub const fn set_addr1 ( & mut self , range : AddrFilter ) {
112
125
self . 0 . addr1_a = range. from ;
113
126
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 ) } ;
117
128
}
118
129
119
- #[ inline]
120
- pub fn addr2 ( & mut self , range : AddrFilterRange ) -> & mut Self {
130
+ pub const fn set_addr2 ( & mut self , range : AddrFilter ) {
121
131
self . 0 . addr2_a = range. from ;
122
132
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 ) } ;
126
134
}
127
135
128
136
#[ inline]
129
- pub fn addr3 ( & mut self , range : AddrFilterRange ) -> & mut Self {
137
+ pub const fn set_addr3 ( & mut self , range : AddrFilter ) {
130
138
self . 0 . addr3_a = range. from ;
131
139
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
+ }
133
142
134
- self
143
+ pub const fn iter ( & self ) -> Iter < ' _ > {
144
+ Iter :: new ( self )
135
145
}
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
+ }
136
188
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)
139
202
}
140
203
}
141
204
@@ -145,12 +208,13 @@ mod test {
145
208
146
209
#[ test]
147
210
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 ( ) ;
154
218
155
219
assert_eq ! ( filter. addr0( ) . from, 1 ) ;
156
220
assert_eq ! ( filter. addr0( ) . to, 2 ) ;
0 commit comments