Skip to content

Commit a354d7d

Browse files
authored
Merge pull request #191 from Freax13/feature/hlat-pw-gpv
enable HLAT, PWA, and GPV when running on TDX
2 parents 4d59649 + 480affb commit a354d7d

File tree

7 files changed

+75
-13
lines changed

7 files changed

+75
-13
lines changed

common/loader/src/elf.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,19 +36,25 @@ pub fn load(
3636
let execute = ph.p_flags.get_bit(0);
3737
let write = ph.p_flags.get_bit(1);
3838
let read = ph.p_flags.get_bit(2);
39+
let _no_verify_guest_paging = ph.p_flags.get_bit(25);
40+
let paging_write_access = ph.p_flags.get_bit(26);
3941
let vmsa_page = ph.p_flags.get_bit(27);
4042
let cpuid_page = ph.p_flags.get_bit(28);
4143
let secrets_page = ph.p_flags.get_bit(29);
4244
let shared_page = ph.p_flags.get_bit(30);
4345

4446
let mut vmpl1_perms = VmplPermissions::empty();
4547
if execute {
46-
vmpl1_perms |= VmplPermissions::EXECUTE_USER;
4748
vmpl1_perms |= VmplPermissions::EXECUTE_SUPERVISOR;
4849
}
4950
if write {
5051
vmpl1_perms |= VmplPermissions::WRITE;
5152
}
53+
// AMD CPUs don't support PWA, so we also need to set the WRITE
54+
// bit for these pages.
55+
if paging_write_access {
56+
vmpl1_perms |= VmplPermissions::WRITE;
57+
}
5258
if read {
5359
vmpl1_perms |= VmplPermissions::READ;
5460
}

common/tdx-types/src/tdcall.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,9 @@ impl MdFieldId {
4343
pub const VMX_GUEST_IA32_EFER: Self = Self::vmcs1(0x2806);
4444
pub const VMX_VM_ENTRY_CONTROL: Self = Self::vmcs1(0x4012);
4545
pub const VMX_VM_EXECUTION_CONTROL_SECONDARY_PROC_BASED: Self = Self::vmcs1(0x401E);
46+
pub const VMX_VM_EXECUTION_CONTROL_TERTIARY_PROC_BASED: Self = Self::vmcs1(0x2034);
47+
pub const VMX_HLATP: Self = Self::vmcs1(0x2040);
48+
pub const VMX_HLAT_PREFIX_SIZE: Self = Self::vmcs1(0x0006);
4649
pub const VMX_GUEST_CS_ARBYTE: Self = Self::vmcs1(0x4816);
4750
pub const VMX_CR0_READ_SHADOW: Self = Self::vmcs1(0x6004);
4851
pub const VMX_CR4_READ_SHADOW: Self = Self::vmcs1(0x6006);

tee/kernel/linker.ld

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@ ENTRY(reset_vector)
33
PHDRS
44
{
55
headers PT_LOAD FILEHDR PHDRS AT(0x08000000000) FLAGS(0);
6-
pagetables PT_LOAD AT(0x10000000000);
6+
pagetables PT_LOAD AT(0x10000000000) FLAGS((1 << 1) | (1 << 2) | (1 << 25));
7+
ropagetables PT_LOAD AT(0x10000010000) FLAGS((1 << 2) | (1 << 26));
78
reset_vector PT_LOAD AT(0x10040000000);
89
text PT_LOAD AT(0x10040200000);
910
rodata PT_LOAD AT(0x10080000000);
@@ -19,12 +20,20 @@ PHDRS
1920
SECTIONS {
2021
.pagetables (0x10000000000) :
2122
{
23+
. = 0x10000000000;
2224
KEEP(*(.pagetables.pml4 .pagetables.pml4.*))
2325
. = 0x10000001000;
2426
KEEP(*(.pagetables.tdx.pml4 .pagetables.tdx.pml4.*))
2527
KEEP(*(.pagetables .pagetables.*))
2628
} :pagetables
2729

30+
.ropagetables (0x10000010000) :
31+
{
32+
. = 0x10000010000;
33+
KEEP(*(.ropagetables.tdx.pml4 .ropagetables.tdx.pml4.*))
34+
KEEP(*(.ropagetables .ropagetables.*))
35+
} :ropagetables
36+
2837
.reset_vector (0xffff800000000000) :
2938
{
3039
KEEP(*(.reset_vector .reset_vector.*))

tee/kernel/src/memory/pagetable.rs

Lines changed: 21 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -57,15 +57,15 @@ static PML4: StaticPml4 = {
5757
page_table
5858
};
5959

60-
#[unsafe(link_section = ".pagetables")]
60+
#[unsafe(link_section = ".ropagetables")]
6161
static PDP_256: StaticPdp = {
6262
let mut page_table = StaticPageTable::new();
6363
page_table.set_table(0, &PD_256_0, flags!(WRITE));
6464
page_table.set_page(1, PROFILER_BUFFER, flags!(WRITE | GLOBAL));
6565
page_table
6666
};
6767

68-
#[unsafe(link_section = ".pagetables")]
68+
#[unsafe(link_section = ".ropagetables")]
6969
static PD_256_0: StaticPd = {
7070
let mut page_table = StaticPageTable::new();
7171
page_table.set_page(0, RESET_VECTOR, flags!(GLOBAL));
@@ -82,7 +82,7 @@ static PD_256_0: StaticPd = {
8282
page_table
8383
};
8484

85-
#[unsafe(link_section = ".pagetables")]
85+
#[unsafe(link_section = ".ropagetables")]
8686
static PDP_352: StaticPdp = {
8787
let mut page_table = StaticPageTable::new();
8888
page_table.set_table(0, &PD_352_0, flags!(WRITE | EXECUTE_DISABLE));
@@ -91,7 +91,7 @@ static PDP_352: StaticPdp = {
9191
page_table
9292
};
9393

94-
#[unsafe(link_section = ".pagetables")]
94+
#[unsafe(link_section = ".ropagetables")]
9595
static PD_352_0: StaticPd = {
9696
let mut page_table = StaticPageTable::new();
9797
page_table.set_page(0, TEXT_SHADOW, flags!(GLOBAL | EXECUTE_DISABLE));
@@ -102,21 +102,21 @@ static PD_352_0: StaticPd = {
102102
page_table
103103
};
104104

105-
#[unsafe(link_section = ".pagetables")]
105+
#[unsafe(link_section = ".ropagetables")]
106106
static PD_352_72: StaticPd = {
107107
let mut page_table = StaticPageTable::new();
108108
page_table.set_page(0, INIT_FILE_SHADOW, flags!(GLOBAL | EXECUTE_DISABLE));
109109
page_table
110110
};
111111

112-
#[unsafe(link_section = ".pagetables")]
112+
#[unsafe(link_section = ".ropagetables")]
113113
static PD_352_80: StaticPd = {
114114
let mut page_table = StaticPageTable::new();
115115
page_table.set_page(0, INPUT_FILE_SHADOW, flags!(GLOBAL | EXECUTE_DISABLE));
116116
page_table
117117
};
118118

119-
#[unsafe(link_section = ".pagetables")]
119+
#[unsafe(link_section = ".ropagetables")]
120120
static PDP_257: StaticPdp = {
121121
let mut page_table = StaticPageTable::new();
122122
page_table.set_page_range(0, DYNAMIC, flags!(WRITE | GLOBAL | EXECUTE_DISABLE));
@@ -131,24 +131,34 @@ static PDP_257: StaticPdp = {
131131
#[used]
132132
#[unsafe(link_section = ".pagetables.tdx.pml4")]
133133
static TDX_PML4: StaticPml4 = {
134+
// Most kernel mappings are set up through the HLAT PML4, so we can start
135+
// with an empty PML4.
136+
let mut page_table = StaticPageTable::new();
137+
page_table.set_recursive_table(510, &TDX_PML4, flags!(WRITE));
138+
page_table
139+
};
140+
141+
#[used]
142+
#[unsafe(link_section = ".ropagetables.tdx.pml4")]
143+
static TDX_HLAT_PML4: StaticPml4 = {
134144
let mut page_table = unsafe { PML4.clone() };
135145
page_table.clear_entry(256);
136146
page_table.set_table(256, &TDX_PDP_256, flags!(WRITE));
137-
// Fix the recursive entry.
147+
// Clear the recursive entry. It should get translated through the regular page tables.
138148
page_table.clear_entry(510);
139-
page_table.set_recursive_table(510, &TDX_PML4, flags!(WRITE));
149+
page_table.fill_hlat_restart();
140150
page_table
141151
};
142152

143-
#[unsafe(link_section = ".pagetables")]
153+
#[unsafe(link_section = ".ropagetables")]
144154
static TDX_PDP_256: StaticPdp = {
145155
let mut page_table = unsafe { PDP_256.clone() };
146156
page_table.clear_entry(0);
147157
page_table.set_table(0, &TDX_PD_256_0, flags!(WRITE));
148158
page_table
149159
};
150160

151-
#[unsafe(link_section = ".pagetables")]
161+
#[unsafe(link_section = ".ropagetables")]
152162
static TDX_PD_256_0: StaticPd = {
153163
let mut page_table = unsafe { PD_256_0.clone() };
154164
page_table.clear_entry(56);

tee/static-page-tables/src/lib.rs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,22 @@ where
115115
}
116116
}
117117

118+
/// Configure all empty entries to restart HLAT translations using the
119+
/// regular translations.
120+
pub const fn fill_hlat_restart(&mut self) {
121+
let flags = flags!(RESTART | PRESENT);
122+
let restart_entry = null::<()>().wrapping_byte_add(flags.0);
123+
124+
let mut i = 0;
125+
while i < 512 {
126+
let entry = self.entries[i].get_mut();
127+
if entry.is_null() {
128+
*entry = restart_entry;
129+
}
130+
i += 1;
131+
}
132+
}
133+
118134
/// Clear an entry.
119135
pub const fn clear_entry(&mut self, index: usize) {
120136
self.entries[index] = UnsafeCell::new(null_mut());
@@ -228,6 +244,7 @@ impl Flags {
228244
pub const DIRTY: Self = Self(1 << 6);
229245
pub const HUGE: Self = Self(1 << 7);
230246
pub const GLOBAL: Self = Self(1 << 8);
247+
pub const RESTART: Self = Self(1 << 11);
231248
pub const C: Self = Self(1 << 51);
232249
pub const S: Self = Self(1 << 51);
233250
pub const EXECUTE_DISABLE: Self = Self(1 << 63);

tee/supervisor-tdx/src/input.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,8 @@ fn load_kernel() {
173173
attrs.set(GpaAttr::READ, ph.flags.get_bit(2));
174174
attrs.set(GpaAttr::WRITE, ph.flags.get_bit(1));
175175
attrs.set(GpaAttr::EXECUTE_SUPERVISOR, ph.flags.get_bit(0));
176+
attrs.set(GpaAttr::VERIFY_GUEST_PAGING, !ph.flags.get_bit(25));
177+
attrs.set(GpaAttr::PAGE_WRITE_ACCESS, ph.flags.get_bit(26));
176178

177179
let start = PhysAddr::new(ph.paddr);
178180
let end = start + (ph.memsz - 1);

tee/supervisor-tdx/src/vcpu.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,21 @@ pub fn init_vcpu() {
9292
);
9393
}
9494

95+
// Enable HLAT, EPT paging-write, and guest-paging verification.
96+
unsafe {
97+
Tdcall::vp_wr(
98+
MdFieldId::VMX_VM_EXECUTION_CONTROL_TERTIARY_PROC_BASED,
99+
(1 << 1) | (1 << 2) | (1 << 3),
100+
(1 << 1) | (1 << 2) | (1 << 3),
101+
);
102+
}
103+
104+
// Configure HLAT.
105+
unsafe {
106+
Tdcall::vp_wr(MdFieldId::VMX_HLAT_PREFIX_SIZE, 1, u64::from(u16::MAX));
107+
Tdcall::vp_wr(MdFieldId::VMX_HLATP, 0x100_0001_0000, !0);
108+
}
109+
95110
// Adjust CS segment.
96111
unsafe {
97112
Tdcall::vp_wr(MdFieldId::VMX_GUEST_CS_ARBYTE, 0xa09b, !0);

0 commit comments

Comments
 (0)