@@ -96,10 +96,70 @@ int hv_post_message(union hv_connection_id connection_id,
9696 return hv_result (status );
9797}
9898
99+ static int hv_alloc_page (void * * page , bool decrypt , const char * note )
100+ {
101+ int ret = 0 ;
102+
103+ /*
104+ * After the page changes its encryption status, its contents might
105+ * appear scrambled on some hardware. Thus `get_zeroed_page` would
106+ * zero the page out in vain, so do that explicitly exactly once.
107+ *
108+ * By default, the page is allocated encrypted in a CoCo VM.
109+ */
110+ * page = (void * )__get_free_page (GFP_KERNEL );
111+ if (!* page )
112+ return - ENOMEM ;
113+
114+ if (decrypt )
115+ ret = set_memory_decrypted ((unsigned long )* page , 1 );
116+ if (ret )
117+ goto failed ;
118+
119+ memset (* page , 0 , PAGE_SIZE );
120+ return 0 ;
121+
122+ failed :
123+ /*
124+ * Report the failure but don't put the page back on the free list as
125+ * its encryption status is unknown.
126+ */
127+ pr_err ("allocation failed for %s page, error %d, decrypted %d\n" ,
128+ note , ret , decrypt );
129+ * page = NULL ;
130+ return ret ;
131+ }
132+
133+ static int hv_free_page (void * * page , bool encrypt , const char * note )
134+ {
135+ int ret = 0 ;
136+
137+ if (!* page )
138+ return 0 ;
139+
140+ if (encrypt )
141+ ret = set_memory_encrypted ((unsigned long )* page , 1 );
142+
143+ /*
144+ * In the case of the failure, the page is leaked. Something is wrong,
145+ * prefer to lose the page with the unknown encryption status and stay afloat.
146+ */
147+ if (ret )
148+ pr_err ("deallocation failed for %s page, error %d, encrypt %d\n" ,
149+ note , ret , encrypt );
150+ else
151+ free_page ((unsigned long )* page );
152+
153+ * page = NULL ;
154+
155+ return ret ;
156+ }
157+
99158int hv_synic_alloc (void )
100159{
101160 int cpu , ret = - ENOMEM ;
102161 struct hv_per_cpu_context * hv_cpu ;
162+ const bool decrypt = !vmbus_is_confidential ();
103163
104164 /*
105165 * First, zero all per-cpu memory areas so hv_synic_free() can
@@ -125,73 +185,37 @@ int hv_synic_alloc(void)
125185 vmbus_on_msg_dpc , (unsigned long )hv_cpu );
126186
127187 if (ms_hyperv .paravisor_present && hv_isolation_type_tdx ()) {
128- hv_cpu -> post_msg_page = ( void * ) get_zeroed_page ( GFP_ATOMIC );
129- if (! hv_cpu -> post_msg_page ) {
130- pr_err ( "Unable to allocate post msg page\n" );
188+ ret = hv_alloc_page ( & hv_cpu -> post_msg_page ,
189+ decrypt , "post msg" );
190+ if ( ret )
131191 goto err ;
132- }
133-
134- ret = set_memory_decrypted ((unsigned long )hv_cpu -> post_msg_page , 1 );
135- if (ret ) {
136- pr_err ("Failed to decrypt post msg page: %d\n" , ret );
137- /* Just leak the page, as it's unsafe to free the page. */
138- hv_cpu -> post_msg_page = NULL ;
139- goto err ;
140- }
141-
142- memset (hv_cpu -> post_msg_page , 0 , PAGE_SIZE );
143192 }
144193
145194 /*
146- * Synic message and event pages are allocated by paravisor.
147- * Skip these pages allocation here.
195+ * If these SynIC pages are not allocated, SIEF and SIM pages
196+ * are configured using what the root partition or the paravisor
197+ * provides upon reading the SIEFP and SIMP registers.
148198 */
149199 if (!ms_hyperv .paravisor_present && !hv_root_partition ()) {
150- hv_cpu -> hyp_synic_message_page =
151- (void * )get_zeroed_page (GFP_ATOMIC );
152- if (!hv_cpu -> hyp_synic_message_page ) {
153- pr_err ("Unable to allocate SYNIC message page\n" );
200+ ret = hv_alloc_page (& hv_cpu -> hyp_synic_message_page ,
201+ decrypt , "hypervisor SynIC msg" );
202+ if (ret )
154203 goto err ;
155- }
156-
157- hv_cpu -> hyp_synic_event_page =
158- (void * )get_zeroed_page (GFP_ATOMIC );
159- if (!hv_cpu -> hyp_synic_event_page ) {
160- pr_err ("Unable to allocate SYNIC event page\n" );
161-
162- free_page ((unsigned long )hv_cpu -> hyp_synic_message_page );
163- hv_cpu -> hyp_synic_message_page = NULL ;
204+ ret = hv_alloc_page (& hv_cpu -> hyp_synic_event_page ,
205+ decrypt , "hypervisor SynIC event" );
206+ if (ret )
164207 goto err ;
165- }
166208 }
167209
168- if (!ms_hyperv .paravisor_present &&
169- (hv_isolation_type_snp () || hv_isolation_type_tdx ())) {
170- ret = set_memory_decrypted ((unsigned long )
171- hv_cpu -> hyp_synic_message_page , 1 );
172- if (ret ) {
173- pr_err ("Failed to decrypt SYNIC msg page: %d\n" , ret );
174- hv_cpu -> hyp_synic_message_page = NULL ;
175-
176- /*
177- * Free the event page here so that hv_synic_free()
178- * won't later try to re-encrypt it.
179- */
180- free_page ((unsigned long )hv_cpu -> hyp_synic_event_page );
181- hv_cpu -> hyp_synic_event_page = NULL ;
210+ if (vmbus_is_confidential ()) {
211+ ret = hv_alloc_page (& hv_cpu -> para_synic_message_page ,
212+ false, "paravisor SynIC msg" );
213+ if (ret )
182214 goto err ;
183- }
184-
185- ret = set_memory_decrypted ((unsigned long )
186- hv_cpu -> hyp_synic_event_page , 1 );
187- if (ret ) {
188- pr_err ("Failed to decrypt SYNIC event page: %d\n" , ret );
189- hv_cpu -> hyp_synic_event_page = NULL ;
215+ ret = hv_alloc_page (& hv_cpu -> para_synic_event_page ,
216+ false, "paravisor SynIC event" );
217+ if (ret )
190218 goto err ;
191- }
192-
193- memset (hv_cpu -> hyp_synic_message_page , 0 , PAGE_SIZE );
194- memset (hv_cpu -> hyp_synic_event_page , 0 , PAGE_SIZE );
195219 }
196220 }
197221
@@ -207,48 +231,28 @@ int hv_synic_alloc(void)
207231
208232void hv_synic_free (void )
209233{
210- int cpu , ret ;
234+ int cpu ;
235+ const bool encrypt = !vmbus_is_confidential ();
211236
212237 for_each_present_cpu (cpu ) {
213238 struct hv_per_cpu_context * hv_cpu =
214239 per_cpu_ptr (hv_context .cpu_context , cpu );
215240
216- /* It's better to leak the page if the encryption fails. */
217- if (ms_hyperv .paravisor_present && hv_isolation_type_tdx ()) {
218- if (hv_cpu -> post_msg_page ) {
219- ret = set_memory_encrypted ((unsigned long )
220- hv_cpu -> post_msg_page , 1 );
221- if (ret ) {
222- pr_err ("Failed to encrypt post msg page: %d\n" , ret );
223- hv_cpu -> post_msg_page = NULL ;
224- }
225- }
241+ if (ms_hyperv .paravisor_present && hv_isolation_type_tdx ())
242+ hv_free_page (& hv_cpu -> post_msg_page ,
243+ encrypt , "post msg" );
244+ if (!ms_hyperv .paravisor_present && !hv_root_partition ()) {
245+ hv_free_page (& hv_cpu -> hyp_synic_event_page ,
246+ encrypt , "hypervisor SynIC event" );
247+ hv_free_page (& hv_cpu -> hyp_synic_message_page ,
248+ encrypt , "hypervisor SynIC msg" );
226249 }
227-
228- if (!ms_hyperv .paravisor_present &&
229- (hv_isolation_type_snp () || hv_isolation_type_tdx ())) {
230- if (hv_cpu -> hyp_synic_message_page ) {
231- ret = set_memory_encrypted ((unsigned long )
232- hv_cpu -> hyp_synic_message_page , 1 );
233- if (ret ) {
234- pr_err ("Failed to encrypt SYNIC msg page: %d\n" , ret );
235- hv_cpu -> hyp_synic_message_page = NULL ;
236- }
237- }
238-
239- if (hv_cpu -> hyp_synic_event_page ) {
240- ret = set_memory_encrypted ((unsigned long )
241- hv_cpu -> hyp_synic_event_page , 1 );
242- if (ret ) {
243- pr_err ("Failed to encrypt SYNIC event page: %d\n" , ret );
244- hv_cpu -> hyp_synic_event_page = NULL ;
245- }
246- }
250+ if (vmbus_is_confidential ()) {
251+ hv_free_page (& hv_cpu -> para_synic_event_page ,
252+ false, "paravisor SynIC event" );
253+ hv_free_page (& hv_cpu -> para_synic_message_page ,
254+ false, "paravisor SynIC msg" );
247255 }
248-
249- free_page ((unsigned long )hv_cpu -> post_msg_page );
250- free_page ((unsigned long )hv_cpu -> hyp_synic_event_page );
251- free_page ((unsigned long )hv_cpu -> hyp_synic_message_page );
252256 }
253257
254258 kfree (hv_context .hv_numa_map );
0 commit comments