Skip to content

Commit 8bec7be

Browse files
authored
Merge pull request #349 from jarkkojs/feat/ucet
User CET Register
2 parents 8ac2487 + 34d0615 commit 8bec7be

File tree

1 file changed

+113
-0
lines changed

1 file changed

+113
-0
lines changed

src/registers/model_specific.rs

+113
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,14 @@ pub struct LStar;
5555
#[derive(Debug)]
5656
pub struct SFMask;
5757

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+
5866
impl Efer {
5967
/// The underlying model specific register.
6068
pub const MSR: Msr = Msr(0xC000_0080);
@@ -90,6 +98,16 @@ impl SFMask {
9098
pub const MSR: Msr = Msr(0xC000_0084);
9199
}
92100

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+
93111
bitflags! {
94112
/// Flags of the Extended Feature Enable Register.
95113
pub struct EferFlags: u64 {
@@ -112,12 +130,37 @@ bitflags! {
112130
}
113131
}
114132

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+
115156
#[cfg(feature = "instructions")]
116157
mod x86_64 {
117158
use super::*;
118159
use crate::addr::VirtAddr;
119160
use crate::registers::rflags::RFlags;
120161
use crate::structures::gdt::SegmentSelector;
162+
use crate::structures::paging::Page;
163+
use crate::structures::paging::Size4KiB;
121164
use crate::PrivilegeLevel;
122165
use bit_field::BitField;
123166
use core::convert::TryInto;
@@ -445,4 +488,74 @@ mod x86_64 {
445488
unsafe { msr.write(value.bits()) };
446489
}
447490
}
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+
}
448561
}

0 commit comments

Comments
 (0)