Skip to content

Commit 9a87977

Browse files
Tianyu Lanliuw
authored andcommitted
Drivers: hv: vmbus: Initialize VMbus ring buffer for Isolation VM
VMbus ring buffer are shared with host and it's need to be accessed via extra address space of Isolation VM with AMD SNP support. This patch is to map the ring buffer address in extra address space via vmap_pfn(). Hyperv set memory host visibility hvcall smears data in the ring buffer and so reset the ring buffer memory to zero after mapping. 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 f2f136c commit 9a87977

File tree

3 files changed

+53
-22
lines changed

3 files changed

+53
-22
lines changed

drivers/hv/Kconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ config HYPERV
88
|| (ARM64 && !CPU_BIG_ENDIAN))
99
select PARAVIRT
1010
select X86_HV_CALLBACK_VECTOR if X86
11+
select VMAP_PFN
1112
help
1213
Select this option to run Linux as a Hyper-V client operating
1314
system.

drivers/hv/channel.c

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -683,15 +683,6 @@ static int __vmbus_open(struct vmbus_channel *newchannel,
683683
if (!newchannel->max_pkt_size)
684684
newchannel->max_pkt_size = VMBUS_DEFAULT_MAX_PKT_SIZE;
685685

686-
err = hv_ringbuffer_init(&newchannel->outbound, page, send_pages, 0);
687-
if (err)
688-
goto error_clean_ring;
689-
690-
err = hv_ringbuffer_init(&newchannel->inbound, &page[send_pages],
691-
recv_pages, newchannel->max_pkt_size);
692-
if (err)
693-
goto error_clean_ring;
694-
695686
/* Establish the gpadl for the ring buffer */
696687
newchannel->ringbuffer_gpadlhandle.gpadl_handle = 0;
697688

@@ -703,6 +694,16 @@ static int __vmbus_open(struct vmbus_channel *newchannel,
703694
if (err)
704695
goto error_clean_ring;
705696

697+
err = hv_ringbuffer_init(&newchannel->outbound,
698+
page, send_pages, 0);
699+
if (err)
700+
goto error_free_gpadl;
701+
702+
err = hv_ringbuffer_init(&newchannel->inbound, &page[send_pages],
703+
recv_pages, newchannel->max_pkt_size);
704+
if (err)
705+
goto error_free_gpadl;
706+
706707
/* Create and init the channel open message */
707708
open_info = kzalloc(sizeof(*open_info) +
708709
sizeof(struct vmbus_channel_open_channel),

drivers/hv/ring_buffer.c

Lines changed: 42 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717
#include <linux/vmalloc.h>
1818
#include <linux/slab.h>
1919
#include <linux/prefetch.h>
20+
#include <linux/io.h>
21+
#include <asm/mshyperv.h>
2022

2123
#include "hyperv_vmbus.h"
2224

@@ -183,32 +185,59 @@ void hv_ringbuffer_pre_init(struct vmbus_channel *channel)
183185
int hv_ringbuffer_init(struct hv_ring_buffer_info *ring_info,
184186
struct page *pages, u32 page_cnt, u32 max_pkt_size)
185187
{
186-
int i;
187188
struct page **pages_wraparound;
189+
unsigned long *pfns_wraparound;
190+
u64 pfn;
191+
int i;
188192

189193
BUILD_BUG_ON((sizeof(struct hv_ring_buffer) != PAGE_SIZE));
190194

191195
/*
192196
* First page holds struct hv_ring_buffer, do wraparound mapping for
193197
* the rest.
194198
*/
195-
pages_wraparound = kcalloc(page_cnt * 2 - 1, sizeof(struct page *),
196-
GFP_KERNEL);
197-
if (!pages_wraparound)
198-
return -ENOMEM;
199+
if (hv_isolation_type_snp()) {
200+
pfn = page_to_pfn(pages) +
201+
PFN_DOWN(ms_hyperv.shared_gpa_boundary);
202+
203+
pfns_wraparound = kcalloc(page_cnt * 2 - 1,
204+
sizeof(unsigned long), GFP_KERNEL);
205+
if (!pfns_wraparound)
206+
return -ENOMEM;
207+
208+
pfns_wraparound[0] = pfn;
209+
for (i = 0; i < 2 * (page_cnt - 1); i++)
210+
pfns_wraparound[i + 1] = pfn + i % (page_cnt - 1) + 1;
199211

200-
pages_wraparound[0] = pages;
201-
for (i = 0; i < 2 * (page_cnt - 1); i++)
202-
pages_wraparound[i + 1] = &pages[i % (page_cnt - 1) + 1];
212+
ring_info->ring_buffer = (struct hv_ring_buffer *)
213+
vmap_pfn(pfns_wraparound, page_cnt * 2 - 1,
214+
PAGE_KERNEL);
215+
kfree(pfns_wraparound);
203216

204-
ring_info->ring_buffer = (struct hv_ring_buffer *)
205-
vmap(pages_wraparound, page_cnt * 2 - 1, VM_MAP, PAGE_KERNEL);
217+
if (!ring_info->ring_buffer)
218+
return -ENOMEM;
219+
220+
/* Zero ring buffer after setting memory host visibility. */
221+
memset(ring_info->ring_buffer, 0x00, PAGE_SIZE * page_cnt);
222+
} else {
223+
pages_wraparound = kcalloc(page_cnt * 2 - 1,
224+
sizeof(struct page *),
225+
GFP_KERNEL);
226+
227+
pages_wraparound[0] = pages;
228+
for (i = 0; i < 2 * (page_cnt - 1); i++)
229+
pages_wraparound[i + 1] =
230+
&pages[i % (page_cnt - 1) + 1];
206231

207-
kfree(pages_wraparound);
232+
ring_info->ring_buffer = (struct hv_ring_buffer *)
233+
vmap(pages_wraparound, page_cnt * 2 - 1, VM_MAP,
234+
PAGE_KERNEL);
208235

236+
kfree(pages_wraparound);
237+
if (!ring_info->ring_buffer)
238+
return -ENOMEM;
239+
}
209240

210-
if (!ring_info->ring_buffer)
211-
return -ENOMEM;
212241

213242
ring_info->ring_buffer->read_index =
214243
ring_info->ring_buffer->write_index = 0;

0 commit comments

Comments
 (0)