summaryrefslogtreecommitdiff
path: root/drivers/hv/ring_buffer.c
diff options
context:
space:
mode:
authorArnaldo Carvalho de Melo <acme@redhat.com>2021-11-06 21:49:33 +0300
committerArnaldo Carvalho de Melo <acme@redhat.com>2021-11-06 21:49:33 +0300
commit7f9f879243d6cf5d2d60d12065e93189cc343387 (patch)
treee74619a16f8291f7225ee9877cf93e530243e0d3 /drivers/hv/ring_buffer.c
parent32f7aa2731b24ad8393f26d63df959d74844345f (diff)
parentfe91c4725aeed35023ba4f7a1e1adfebb6878c23 (diff)
downloadlinux-7f9f879243d6cf5d2d60d12065e93189cc343387.tar.xz
Merge remote-tracking branch 'torvalds/master' into perf/core
To pick up some tools/perf/ patches that went via tip/perf/core, such as: tools/perf: Add mem_hops field in perf_mem_data_src structure Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'drivers/hv/ring_buffer.c')
-rw-r--r--drivers/hv/ring_buffer.c57
1 files changed, 44 insertions, 13 deletions
diff --git a/drivers/hv/ring_buffer.c b/drivers/hv/ring_buffer.c
index 314015d9e912..71efacb90965 100644
--- a/drivers/hv/ring_buffer.c
+++ b/drivers/hv/ring_buffer.c
@@ -17,6 +17,8 @@
#include <linux/vmalloc.h>
#include <linux/slab.h>
#include <linux/prefetch.h>
+#include <linux/io.h>
+#include <asm/mshyperv.h>
#include "hyperv_vmbus.h"
@@ -183,8 +185,10 @@ void hv_ringbuffer_pre_init(struct vmbus_channel *channel)
int hv_ringbuffer_init(struct hv_ring_buffer_info *ring_info,
struct page *pages, u32 page_cnt, u32 max_pkt_size)
{
- int i;
struct page **pages_wraparound;
+ unsigned long *pfns_wraparound;
+ u64 pfn;
+ int i;
BUILD_BUG_ON((sizeof(struct hv_ring_buffer) != PAGE_SIZE));
@@ -192,23 +196,50 @@ int hv_ringbuffer_init(struct hv_ring_buffer_info *ring_info,
* First page holds struct hv_ring_buffer, do wraparound mapping for
* the rest.
*/
- pages_wraparound = kcalloc(page_cnt * 2 - 1, sizeof(struct page *),
- GFP_KERNEL);
- if (!pages_wraparound)
- return -ENOMEM;
+ if (hv_isolation_type_snp()) {
+ pfn = page_to_pfn(pages) +
+ PFN_DOWN(ms_hyperv.shared_gpa_boundary);
+
+ pfns_wraparound = kcalloc(page_cnt * 2 - 1,
+ sizeof(unsigned long), GFP_KERNEL);
+ if (!pfns_wraparound)
+ return -ENOMEM;
- pages_wraparound[0] = pages;
- for (i = 0; i < 2 * (page_cnt - 1); i++)
- pages_wraparound[i + 1] = &pages[i % (page_cnt - 1) + 1];
+ pfns_wraparound[0] = pfn;
+ for (i = 0; i < 2 * (page_cnt - 1); i++)
+ pfns_wraparound[i + 1] = pfn + i % (page_cnt - 1) + 1;
- ring_info->ring_buffer = (struct hv_ring_buffer *)
- vmap(pages_wraparound, page_cnt * 2 - 1, VM_MAP, PAGE_KERNEL);
+ ring_info->ring_buffer = (struct hv_ring_buffer *)
+ vmap_pfn(pfns_wraparound, page_cnt * 2 - 1,
+ PAGE_KERNEL);
+ kfree(pfns_wraparound);
- kfree(pages_wraparound);
+ if (!ring_info->ring_buffer)
+ return -ENOMEM;
+ /* Zero ring buffer after setting memory host visibility. */
+ memset(ring_info->ring_buffer, 0x00, PAGE_SIZE * page_cnt);
+ } else {
+ pages_wraparound = kcalloc(page_cnt * 2 - 1,
+ sizeof(struct page *),
+ GFP_KERNEL);
+ if (!pages_wraparound)
+ return -ENOMEM;
+
+ pages_wraparound[0] = pages;
+ for (i = 0; i < 2 * (page_cnt - 1); i++)
+ pages_wraparound[i + 1] =
+ &pages[i % (page_cnt - 1) + 1];
+
+ ring_info->ring_buffer = (struct hv_ring_buffer *)
+ vmap(pages_wraparound, page_cnt * 2 - 1, VM_MAP,
+ PAGE_KERNEL);
+
+ kfree(pages_wraparound);
+ if (!ring_info->ring_buffer)
+ return -ENOMEM;
+ }
- if (!ring_info->ring_buffer)
- return -ENOMEM;
ring_info->ring_buffer->read_index =
ring_info->ring_buffer->write_index = 0;