From: Tianyu Lan <Tianyu.Lan@xxxxxxxxxxxxx> Initialize/free bounce buffer resource when add/delete vmbus channel in Isolation VM. Signed-off-by: Sunil Muthuswamy <sunilmut@xxxxxxxxxxxxx> Co-Developed-by: Sunil Muthuswamy <sunilmut@xxxxxxxxxxxxx> Signed-off-by: Tianyu Lan <Tianyu.Lan@xxxxxxxxxxxxx> --- 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@xxxxxxxxxxxxx> + * Tianyu Lan <Tianyu.Lan@xxxxxxxxxxxxx> + */ +#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