Skip to content

Commit f2f136c

Browse files
Tianyu Lanliuw
authored andcommitted
Drivers: hv: vmbus: Add SNP support for VMbus channel initiate message
The monitor pages in the CHANNELMSG_INITIATE_CONTACT msg are shared with host in Isolation VM and so it's necessary to use hvcall to set them visible to host. In Isolation VM with AMD SEV SNP, the access address should be in the extra space which is above shared gpa boundary. So remap these pages into the extra address(pa + shared_gpa_boundary). Introduce monitor_pages_original[] in the struct vmbus_connection to store monitor page virtual address returned by hv_alloc_hyperv_ zeroed_page() and free monitor page via monitor_pages_original in the vmbus_disconnect(). The monitor_pages[] is to used to access monitor page and it is initialized to be equal with monitor_pages_ original. The monitor_pages[] will be overridden in the isolation VM with va of extra address. Introduce monitor_pages_pa[] to store monitor pages' physical address and use it to populate pa in the initiate msg. Reviewed-by: Michael Kelley <[email protected]> Signed-off-by: Tianyu Lan <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Wei Liu <[email protected]>
1 parent 20c89a5 commit f2f136c

File tree

2 files changed

+91
-6
lines changed

2 files changed

+91
-6
lines changed

drivers/hv/connection.c

Lines changed: 89 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@
1919
#include <linux/vmalloc.h>
2020
#include <linux/hyperv.h>
2121
#include <linux/export.h>
22+
#include <linux/io.h>
23+
#include <linux/set_memory.h>
2224
#include <asm/mshyperv.h>
2325

2426
#include "hyperv_vmbus.h"
@@ -102,8 +104,9 @@ int vmbus_negotiate_version(struct vmbus_channel_msginfo *msginfo, u32 version)
102104
vmbus_connection.msg_conn_id = VMBUS_MESSAGE_CONNECTION_ID;
103105
}
104106

105-
msg->monitor_page1 = virt_to_phys(vmbus_connection.monitor_pages[0]);
106-
msg->monitor_page2 = virt_to_phys(vmbus_connection.monitor_pages[1]);
107+
msg->monitor_page1 = vmbus_connection.monitor_pages_pa[0];
108+
msg->monitor_page2 = vmbus_connection.monitor_pages_pa[1];
109+
107110
msg->target_vcpu = hv_cpu_number_to_vp_number(VMBUS_CONNECT_CPU);
108111

109112
/*
@@ -216,6 +219,65 @@ int vmbus_connect(void)
216219
goto cleanup;
217220
}
218221

222+
vmbus_connection.monitor_pages_original[0]
223+
= vmbus_connection.monitor_pages[0];
224+
vmbus_connection.monitor_pages_original[1]
225+
= vmbus_connection.monitor_pages[1];
226+
vmbus_connection.monitor_pages_pa[0]
227+
= virt_to_phys(vmbus_connection.monitor_pages[0]);
228+
vmbus_connection.monitor_pages_pa[1]
229+
= virt_to_phys(vmbus_connection.monitor_pages[1]);
230+
231+
if (hv_is_isolation_supported()) {
232+
ret = set_memory_decrypted((unsigned long)
233+
vmbus_connection.monitor_pages[0],
234+
1);
235+
ret |= set_memory_decrypted((unsigned long)
236+
vmbus_connection.monitor_pages[1],
237+
1);
238+
if (ret)
239+
goto cleanup;
240+
241+
/*
242+
* Isolation VM with AMD SNP needs to access monitor page via
243+
* address space above shared gpa boundary.
244+
*/
245+
if (hv_isolation_type_snp()) {
246+
vmbus_connection.monitor_pages_pa[0] +=
247+
ms_hyperv.shared_gpa_boundary;
248+
vmbus_connection.monitor_pages_pa[1] +=
249+
ms_hyperv.shared_gpa_boundary;
250+
251+
vmbus_connection.monitor_pages[0]
252+
= memremap(vmbus_connection.monitor_pages_pa[0],
253+
HV_HYP_PAGE_SIZE,
254+
MEMREMAP_WB);
255+
if (!vmbus_connection.monitor_pages[0]) {
256+
ret = -ENOMEM;
257+
goto cleanup;
258+
}
259+
260+
vmbus_connection.monitor_pages[1]
261+
= memremap(vmbus_connection.monitor_pages_pa[1],
262+
HV_HYP_PAGE_SIZE,
263+
MEMREMAP_WB);
264+
if (!vmbus_connection.monitor_pages[1]) {
265+
ret = -ENOMEM;
266+
goto cleanup;
267+
}
268+
}
269+
270+
/*
271+
* Set memory host visibility hvcall smears memory
272+
* and so zero monitor pages here.
273+
*/
274+
memset(vmbus_connection.monitor_pages[0], 0x00,
275+
HV_HYP_PAGE_SIZE);
276+
memset(vmbus_connection.monitor_pages[1], 0x00,
277+
HV_HYP_PAGE_SIZE);
278+
279+
}
280+
219281
msginfo = kzalloc(sizeof(*msginfo) +
220282
sizeof(struct vmbus_channel_initiate_contact),
221283
GFP_KERNEL);
@@ -303,10 +365,31 @@ void vmbus_disconnect(void)
303365
vmbus_connection.int_page = NULL;
304366
}
305367

306-
hv_free_hyperv_page((unsigned long)vmbus_connection.monitor_pages[0]);
307-
hv_free_hyperv_page((unsigned long)vmbus_connection.monitor_pages[1]);
308-
vmbus_connection.monitor_pages[0] = NULL;
309-
vmbus_connection.monitor_pages[1] = NULL;
368+
if (hv_is_isolation_supported()) {
369+
/*
370+
* memunmap() checks input address is ioremap address or not
371+
* inside. It doesn't unmap any thing in the non-SNP CVM and
372+
* so not check CVM type here.
373+
*/
374+
memunmap(vmbus_connection.monitor_pages[0]);
375+
memunmap(vmbus_connection.monitor_pages[1]);
376+
377+
set_memory_encrypted((unsigned long)
378+
vmbus_connection.monitor_pages_original[0],
379+
1);
380+
set_memory_encrypted((unsigned long)
381+
vmbus_connection.monitor_pages_original[1],
382+
1);
383+
}
384+
385+
hv_free_hyperv_page((unsigned long)
386+
vmbus_connection.monitor_pages_original[0]);
387+
hv_free_hyperv_page((unsigned long)
388+
vmbus_connection.monitor_pages_original[1]);
389+
vmbus_connection.monitor_pages_original[0] =
390+
vmbus_connection.monitor_pages[0] = NULL;
391+
vmbus_connection.monitor_pages_original[1] =
392+
vmbus_connection.monitor_pages[1] = NULL;
310393
}
311394

312395
/*

drivers/hv/hyperv_vmbus.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -240,6 +240,8 @@ struct vmbus_connection {
240240
* is child->parent notification
241241
*/
242242
struct hv_monitor_page *monitor_pages[2];
243+
void *monitor_pages_original[2];
244+
phys_addr_t monitor_pages_pa[2];
243245
struct list_head chn_msg_list;
244246
spinlock_t channelmsg_lock;
245247

0 commit comments

Comments
 (0)