[RFC PATCH 8/12] x86/Hyper-V: Initialize bounce buffer page cache and list
From: Tianyu Lan <hidden>
Date: 2021-02-28 15:09:07
Also in:
lkml
Subsystem:
hyper-v/azure core and drivers, the rest · Maintainers:
"K. Y. Srinivasan", Haiyang Zhang, Wei Liu, Dexuan Cui, Long Li, Linus Torvalds
From: Tianyu Lan <redacted> Initialize/free bounce buffer resource when add/delete vmbus channel in Isolation VM. Signed-off-by: Sunil Muthuswamy <redacted> Co-Developed-by: Sunil Muthuswamy <redacted> Signed-off-by: Tianyu Lan <redacted> --- drivers/hv/Makefile | 2 +- drivers/hv/channel_mgmt.c | 29 +++++++++++++++++---------- drivers/hv/hv_bounce.c | 42 +++++++++++++++++++++++++++++++++++++++ drivers/hv/hyperv_vmbus.h | 14 +++++++++++++ include/linux/hyperv.h | 22 ++++++++++++++++++++ 5 files changed, 97 insertions(+), 12 deletions(-) create mode 100644 drivers/hv/hv_bounce.c
diff --git a/drivers/hv/Makefile b/drivers/hv/Makefile
index 94daf8240c95..b0c20fed9153 100644
--- a/drivers/hv/Makefile
+++ b/drivers/hv/Makefile@@ -8,6 +8,6 @@ CFLAGS_hv_balloon.o = -I$(src) hv_vmbus-y := vmbus_drv.o \ hv.o connection.o channel.o \ - channel_mgmt.o ring_buffer.o hv_trace.o + channel_mgmt.o ring_buffer.o hv_trace.o hv_bounce.o hv_vmbus-$(CONFIG_HYPERV_TESTING) += hv_debugfs.o hv_utils-y := hv_util.o hv_kvp.o hv_snapshot.o hv_fcopy.o hv_utils_transport.o
diff --git a/drivers/hv/channel_mgmt.c b/drivers/hv/channel_mgmt.c
index f0ed730e2e4e..e2846cacfd70 100644
--- a/drivers/hv/channel_mgmt.c
+++ b/drivers/hv/channel_mgmt.c@@ -336,6 +336,18 @@ bool vmbus_prep_negotiate_resp(struct icmsg_hdr *icmsghdrp, u8 *buf, EXPORT_SYMBOL_GPL(vmbus_prep_negotiate_resp); +/* + * free_channel - Release the resources used by the vmbus channel object + */ +static void free_channel(struct vmbus_channel *channel) +{ + tasklet_kill(&channel->callback_event); + vmbus_remove_channel_attr_group(channel); + + kobject_put(&channel->kobj); + hv_free_channel_ivm(channel); +} + /* * alloc_channel - Allocate and initialize a vmbus channel object */
@@ -360,17 +372,6 @@ static struct vmbus_channel *alloc_channel(void) return channel; } -/* - * free_channel - Release the resources used by the vmbus channel object - */ -static void free_channel(struct vmbus_channel *channel) -{ - tasklet_kill(&channel->callback_event); - vmbus_remove_channel_attr_group(channel); - - kobject_put(&channel->kobj); -} - void vmbus_channel_map_relid(struct vmbus_channel *channel) { if (WARN_ON(channel->offermsg.child_relid >= MAX_CHANNEL_RELIDS))
@@ -510,6 +511,8 @@ static void vmbus_add_channel_work(struct work_struct *work) if (vmbus_add_channel_kobj(dev, newchannel)) goto err_deq_chan; + hv_init_channel_ivm(newchannel); + if (primary_channel->sc_creation_callback != NULL) primary_channel->sc_creation_callback(newchannel);
@@ -543,6 +546,10 @@ static void vmbus_add_channel_work(struct work_struct *work) } newchannel->probe_done = true; + + if (hv_init_channel_ivm(newchannel)) + goto err_deq_chan; + return; err_deq_chan:
diff --git a/drivers/hv/hv_bounce.c b/drivers/hv/hv_bounce.c
new file mode 100644
index 000000000000..c5898325b238
--- /dev/null
+++ b/drivers/hv/hv_bounce.c@@ -0,0 +1,42 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Bounce buffer code for Hyper-V Isolation VM support. + * + * Authors: + * Sunil Muthuswamy <sunilmut@microsoft.com> + * Tianyu Lan <Tianyu.Lan@microsoft.com> + */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include "hyperv_vmbus.h" + +int hv_init_channel_ivm(struct vmbus_channel *channel) +{ + if (!hv_is_isolation_supported()) + return 0; + + INIT_LIST_HEAD(&channel->bounce_page_free_head); + INIT_LIST_HEAD(&channel->bounce_pkt_free_list_head); + + channel->bounce_pkt_cache = KMEM_CACHE(hv_bounce_pkt, 0); + if (unlikely(!channel->bounce_pkt_cache)) + return -ENOMEM; + channel->bounce_page_cache = KMEM_CACHE(hv_bounce_page_list, 0); + if (unlikely(!channel->bounce_page_cache)) + return -ENOMEM; + + return 0; +} + +void hv_free_channel_ivm(struct vmbus_channel *channel) +{ + if (!hv_is_isolation_supported()) + return; + + + cancel_delayed_work_sync(&channel->bounce_page_list_maintain); + hv_bounce_pkt_list_free(channel, &channel->bounce_pkt_free_list_head); + hv_bounce_page_list_free(channel, &channel->bounce_page_free_head); + kmem_cache_destroy(channel->bounce_pkt_cache); + kmem_cache_destroy(channel->bounce_page_cache); +}
diff --git a/drivers/hv/hyperv_vmbus.h b/drivers/hv/hyperv_vmbus.h
index d78a04ad5490..7edf2be60d2c 100644
--- a/drivers/hv/hyperv_vmbus.h
+++ b/drivers/hv/hyperv_vmbus.h@@ -19,6 +19,7 @@ #include <linux/hyperv.h> #include <linux/interrupt.h> +#include <asm/mshyperv.h> #include "hv_trace.h" /*
@@ -56,6 +57,19 @@ union hv_monitor_trigger_state { }; }; +/* + * All vmbus channels initially start with zero bounce pages and are required + * to set any non-zero size, if needed. + */ +#define HV_DEFAULT_BOUNCE_BUFFER_PAGES 0 + +/* MIN should be a power of 2 */ +#define HV_MIN_BOUNCE_BUFFER_PAGES 64 + +extern int hv_init_channel_ivm(struct vmbus_channel *channel); + +extern void hv_free_channel_ivm(struct vmbus_channel *channel); + /* struct hv_monitor_page Layout */ /* ------------------------------------------------------ */ /* | 0 | TriggerState (4 bytes) | Rsvd1 (4 bytes) | */
diff --git a/include/linux/hyperv.h b/include/linux/hyperv.h
index 41cbaa2db567..d518aba17565 100644
--- a/include/linux/hyperv.h
+++ b/include/linux/hyperv.h@@ -25,6 +25,9 @@ #include <linux/interrupt.h> #include <linux/reciprocal_div.h> #include <asm/hyperv-tlfs.h> +#include <linux/slab.h> +#include <linux/mempool.h> +#include <linux/mempool.h> #define MAX_PAGE_BUFFER_COUNT 32 #define MAX_MULTIPAGE_BUFFER_COUNT 32 /* 128K */
@@ -1007,9 +1010,28 @@ struct vmbus_channel { u32 fuzz_testing_interrupt_delay; u32 fuzz_testing_message_delay; + /* request/transaction ids for VMBus */ struct vmbus_requestor requestor; u32 rqstor_size; + /* + * Minimum number of bounce resources (i.e bounce packets & pages) that + * should be allocated and reserved for this channel. Allocation is + * permitted to go beyond this limit, and the maintenance task takes + * care of releasing the extra allocated resources. + */ + u32 min_bounce_resource_count; + + /* The free list of bounce pages is LRU sorted based on last used */ + struct list_head bounce_page_free_head; + u32 bounce_page_alloc_count; + struct delayed_work bounce_page_list_maintain; + + struct kmem_cache *bounce_page_cache; + struct kmem_cache *bounce_pkt_cache; + struct list_head bounce_pkt_free_list_head; + u32 bounce_pkt_free_count; + spinlock_t bp_lock; }; u64 vmbus_next_request_id(struct vmbus_requestor *rqstor, u64 rqst_addr);
--
2.25.1