@@ -55,6 +55,14 @@ pub struct LStar;
55
55
#[ derive( Debug ) ]
56
56
pub struct SFMask ;
57
57
58
+ /// IA32_U_CET: user mode CET configuration
59
+ #[ derive( Debug ) ]
60
+ pub struct UCet ;
61
+
62
+ /// IA32_S_CET: supervisor mode CET configuration
63
+ #[ derive( Debug ) ]
64
+ pub struct SCet ;
65
+
58
66
impl Efer {
59
67
/// The underlying model specific register.
60
68
pub const MSR : Msr = Msr ( 0xC000_0080 ) ;
@@ -90,6 +98,16 @@ impl SFMask {
90
98
pub const MSR : Msr = Msr ( 0xC000_0084 ) ;
91
99
}
92
100
101
+ impl UCet {
102
+ /// The underlying model specific register.
103
+ pub const MSR : Msr = Msr ( 0x6A0 ) ;
104
+ }
105
+
106
+ impl SCet {
107
+ /// The underlying model specific register.
108
+ pub const MSR : Msr = Msr ( 0x6A2 ) ;
109
+ }
110
+
93
111
bitflags ! {
94
112
/// Flags of the Extended Feature Enable Register.
95
113
pub struct EferFlags : u64 {
@@ -112,12 +130,37 @@ bitflags! {
112
130
}
113
131
}
114
132
133
+ bitflags ! {
134
+ /// Flags stored in IA32_U_CET and IA32_S_CET (Table-2-2 in Intel SDM Volume
135
+ /// 4). The Intel SDM-equivalent names are described in parentheses.
136
+ pub struct CetFlags : u64 {
137
+ /// Enable shadow stack (SH_STK_EN)
138
+ const SS_ENABLE = 1 << 0 ;
139
+ /// Enable WRSS{D,Q}W instructions (WR_SHTK_EN)
140
+ const SS_WRITE_ENABLE = 1 << 1 ;
141
+ /// Enable indirect branch tracking (ENDBR_EN)
142
+ const IBT_ENABLE = 1 << 2 ;
143
+ /// Enable legacy treatment for indirect branch tracking (LEG_IW_EN)
144
+ const IBT_LEGACY_ENABLE = 1 << 3 ;
145
+ /// Enable no-track opcode prefix for indirect branch tracking (NO_TRACK_EN)
146
+ const IBT_NO_TRACK_ENABLE = 1 << 4 ;
147
+ /// Disable suppression of CET on legacy compatibility (SUPPRESS_DIS)
148
+ const IBT_LEGACY_SUPPRESS_ENABLE = 1 << 5 ;
149
+ /// Enable suppression of indirect branch tracking (SUPPRESS)
150
+ const IBT_SUPPRESS_ENABLE = 1 << 10 ;
151
+ /// Is IBT waiting for a branch to return? (read-only, TRACKER)
152
+ const IBT_TRACKED = 1 << 11 ;
153
+ }
154
+ }
155
+
115
156
#[ cfg( feature = "instructions" ) ]
116
157
mod x86_64 {
117
158
use super :: * ;
118
159
use crate :: addr:: VirtAddr ;
119
160
use crate :: registers:: rflags:: RFlags ;
120
161
use crate :: structures:: gdt:: SegmentSelector ;
162
+ use crate :: structures:: paging:: Page ;
163
+ use crate :: structures:: paging:: Size4KiB ;
121
164
use crate :: PrivilegeLevel ;
122
165
use bit_field:: BitField ;
123
166
use core:: convert:: TryInto ;
@@ -445,4 +488,74 @@ mod x86_64 {
445
488
unsafe { msr. write ( value. bits ( ) ) } ;
446
489
}
447
490
}
491
+
492
+ impl UCet {
493
+ /// Read the raw IA32_U_CET.
494
+ #[ inline]
495
+ fn read_raw ( ) -> u64 {
496
+ unsafe { Self :: MSR . read ( ) }
497
+ }
498
+
499
+ /// Write the raw IA32_U_CET.
500
+ #[ inline]
501
+ fn write_raw ( value : u64 ) {
502
+ let mut msr = Self :: MSR ;
503
+ unsafe {
504
+ msr. write ( value) ;
505
+ }
506
+ }
507
+
508
+ /// Read IA32_U_CET. Returns a tuple of the flags and the address to the legacy code page bitmap.
509
+ #[ inline]
510
+ pub fn read ( ) -> ( CetFlags , Page ) {
511
+ let value = Self :: read_raw ( ) ;
512
+ let cet_flags = CetFlags :: from_bits_truncate ( value) ;
513
+ let legacy_bitmap =
514
+ Page :: from_start_address ( VirtAddr :: new ( value & !( Page :: < Size4KiB > :: SIZE - 1 ) ) )
515
+ . unwrap ( ) ;
516
+
517
+ ( cet_flags, legacy_bitmap)
518
+ }
519
+
520
+ /// Write IA32_U_CET.
521
+ #[ inline]
522
+ pub fn write ( flags : CetFlags , legacy_bitmap : Page ) {
523
+ Self :: write_raw ( flags. bits ( ) | legacy_bitmap. start_address ( ) . as_u64 ( ) ) ;
524
+ }
525
+ }
526
+
527
+ impl SCet {
528
+ /// Read the raw IA32_S_CET.
529
+ #[ inline]
530
+ fn read_raw ( ) -> u64 {
531
+ unsafe { Self :: MSR . read ( ) }
532
+ }
533
+
534
+ /// Write the raw IA32_S_CET.
535
+ #[ inline]
536
+ fn write_raw ( value : u64 ) {
537
+ let mut msr = Self :: MSR ;
538
+ unsafe {
539
+ msr. write ( value) ;
540
+ }
541
+ }
542
+
543
+ /// Read IA32_S_CET. Returns a tuple of the flags and the address to the legacy code page bitmap.
544
+ #[ inline]
545
+ pub fn read ( ) -> ( CetFlags , Page ) {
546
+ let value = Self :: read_raw ( ) ;
547
+ let cet_flags = CetFlags :: from_bits_truncate ( value) ;
548
+ let legacy_bitmap =
549
+ Page :: from_start_address ( VirtAddr :: new ( value & !( Page :: < Size4KiB > :: SIZE - 1 ) ) )
550
+ . unwrap ( ) ;
551
+
552
+ ( cet_flags, legacy_bitmap)
553
+ }
554
+
555
+ /// Write IA32_S_CET.
556
+ #[ inline]
557
+ pub fn write ( flags : CetFlags , legacy_bitmap : Page ) {
558
+ Self :: write_raw ( flags. bits ( ) | legacy_bitmap. start_address ( ) . as_u64 ( ) ) ;
559
+ }
560
+ }
448
561
}
0 commit comments