1+ use crate :: error:: { PtError , PtErrorCode } ;
12use libipt_sys:: pt_conf_addr_filter;
23use 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 ) ]
99pub 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+
4150impl 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 ) ;
0 commit comments