1
1
// Copyright (c) Microsoft Corporation.
2
2
// Licensed under the MIT License.
3
3
4
+ use crate :: arch:: tdx:: TdcallInstruction ;
5
+ use crate :: arch:: x86_64:: address_space:: tdx_share_large_page;
6
+ use crate :: arch:: x86_64:: address_space:: tdx_unshare_large_page;
7
+ use crate :: host_params:: shim_params:: IsolationType ;
8
+ use crate :: MemoryRange ;
9
+ use core:: arch:: asm;
4
10
use core:: ptr:: addr_of;
5
11
use hvdef:: HV_PAGE_SIZE ;
6
12
use minimal_rt:: arch:: hypercall:: HYPERCALL_PAGE ;
7
13
use minimal_rt:: arch:: msr:: read_msr;
8
14
use minimal_rt:: arch:: msr:: write_msr;
15
+ use tdcall:: tdcall_wrmsr;
9
16
10
17
/// Writes an MSR to tell the hypervisor the OS ID for the boot shim.
11
- fn report_os_id ( guest_os_id : u64 ) {
12
- // SAFETY: Using the contract established in the Hyper-V TLFS.
13
- unsafe {
14
- write_msr ( hvdef:: HV_X64_MSR_GUEST_OS_ID , guest_os_id) ;
15
- } ;
18
+ fn report_os_id ( guest_os_id : u64 , isolation : IsolationType ) {
19
+ match isolation {
20
+ IsolationType :: Tdx => {
21
+ tdcall_wrmsr (
22
+ & mut TdcallInstruction ,
23
+ hvdef:: HV_X64_MSR_GUEST_OS_ID ,
24
+ guest_os_id,
25
+ )
26
+ . unwrap ( ) ;
27
+ }
28
+ _ => {
29
+ // SAFETY: Using the contract established in the Hyper-V TLFS.
30
+ unsafe {
31
+ write_msr ( hvdef:: HV_X64_MSR_GUEST_OS_ID , guest_os_id) ;
32
+ } ;
33
+ }
34
+ }
16
35
}
17
36
18
37
/// Writes an MSR to tell the hypervisor where the hypercall page is
@@ -36,15 +55,77 @@ fn write_hypercall_msr(enable: bool) {
36
55
}
37
56
38
57
/// Has to be called before using hypercalls.
39
- pub ( crate ) fn initialize ( guest_os_id : u64 ) {
58
+ pub ( crate ) fn initialize (
59
+ guest_os_id : u64 ,
60
+ isolation : IsolationType ,
61
+ input_page : Option < u64 > ,
62
+ output_page : Option < u64 > ,
63
+ ) {
40
64
// We are assuming we are running under a Microsoft hypervisor, so there is
41
65
// no need to check any cpuid leaves.
42
- report_os_id ( guest_os_id) ;
43
- write_hypercall_msr ( true ) ;
66
+ report_os_id ( guest_os_id, isolation) ;
67
+
68
+ match isolation {
69
+ IsolationType :: Tdx => {
70
+ // SAFETY: The hypercall i/o pages are valid virtual addresses owned by the caller
71
+ unsafe {
72
+ tdx_share_large_page ( input_page. unwrap ( ) ) ;
73
+ tdx_share_large_page ( output_page. unwrap ( ) ) ;
74
+ }
75
+
76
+ //// Enable host visibility for hypercall page
77
+ let input_page_range =
78
+ MemoryRange :: new ( input_page. unwrap ( ) ..input_page. unwrap ( ) + 4096 ) ;
79
+ let output_page_range =
80
+ MemoryRange :: new ( output_page. unwrap ( ) ..output_page. unwrap ( ) + 4096 ) ;
81
+ super :: tdx:: change_page_visibility ( input_page_range, true ) ;
82
+ super :: tdx:: change_page_visibility ( output_page_range, true ) ;
83
+ }
84
+
85
+ _ => {
86
+ write_hypercall_msr ( true ) ;
87
+ }
88
+ }
44
89
}
45
90
46
91
/// Call before jumping to kernel.
47
- pub ( crate ) fn uninitialize ( ) {
48
- write_hypercall_msr ( false ) ;
49
- report_os_id ( 0 ) ;
92
+ pub ( crate ) fn uninitialize (
93
+ isolation : IsolationType ,
94
+ input_page : Option < u64 > ,
95
+ output_page : Option < u64 > ,
96
+ ) {
97
+ report_os_id ( 0 , isolation) ;
98
+
99
+ match isolation {
100
+ IsolationType :: Tdx => {
101
+ // SAFETY: The hypercall i/o pages are valid virtual addresses owned by the caller
102
+ unsafe {
103
+ tdx_unshare_large_page ( input_page. unwrap ( ) ) ;
104
+ tdx_unshare_large_page ( output_page. unwrap ( ) ) ;
105
+ }
106
+
107
+ // Disable host visibility for hypercall page
108
+ let input_page_range =
109
+ MemoryRange :: new ( input_page. unwrap ( ) ..input_page. unwrap ( ) + 4096 ) ;
110
+ super :: tdx:: change_page_visibility ( input_page_range, false ) ;
111
+ let output_page_range =
112
+ MemoryRange :: new ( output_page. unwrap ( ) ..output_page. unwrap ( ) + 4096 ) ;
113
+ super :: tdx:: change_page_visibility ( output_page_range, false ) ;
114
+ super :: tdx:: accept_pages ( input_page_range)
115
+ . expect ( "accepting vtl 2 memory must not fail" ) ;
116
+ super :: tdx:: accept_pages ( output_page_range)
117
+ . expect ( "accepting vtl 2 memory must not fail" ) ;
118
+
119
+ // SAFETY: Flush TLB
120
+ unsafe {
121
+ asm ! {
122
+ "mov rax, cr3" ,
123
+ "mov cr3, rax"
124
+ }
125
+ }
126
+ }
127
+ _ => {
128
+ write_hypercall_msr ( false ) ;
129
+ }
130
+ }
50
131
}
0 commit comments