drivers: hv
Subsystems (2)
cover drivers: hv
This patch-set does some cleanup of the KVP component. Also included is a patch that will remove artificial limitation on the number of VCPUs that can be assigned to the Linux guest on Hyper-V. This is a resend of a subset of the patches that was sent earlier. Of the original 6 patch set, the first two were applied. I am re-sending the remaining four with the changes Greg wanted.
Regards,
K. Y
PATCH 1/4 drivers: hv: Cleanup the kvp related state in hyperv.h
Now cleanup the hyperv.h with regards to KVP definitions.
--- include/linux/hyperv.h | 27 ++++++++++++++------------- 1 files changed, 14 insertions(+), 13 deletions(-)
include/linux/hyperv.h +14 -13
@@ -137,7 +137,6 @@ struct hv_ku_msg { -#ifdef __KERNEL__/* * Registry value types.
@@ -163,28 +162,30 @@ enum hv_kvp_exchg_pool { };struct hv_kvp_hdr { -u8 operation; -u8 pool; -}; +__u8 operation; +__u8 pool; +__u16 pad; +} __attribute__((packed));struct hv_kvp_exchg_msg_value { -u32 value_type; -u32 key_size; -u32 value_size; -u8 key[HV_KVP_EXCHANGE_MAX_KEY_SIZE ]; -u8 value[HV_KVP_EXCHANGE_MAX_VALUE_SIZE ]; -}; +__u32 value_type; +__u32 key_size; +__u32 value_size; +__u8 key[HV_KVP_EXCHANGE_MAX_KEY_SIZE ]; +__u8 value[HV_KVP_EXCHANGE_MAX_VALUE_SIZE ]; +} __attribute__((packed));struct hv_kvp_msg_enumerate { -u32 index; +__u32 index;struct hv_kvp_exchg_msg_value data; -}; +} __attribute__((packed));struct hv_kvp_msg {struct hv_kvp_hdr kvp_hdr;struct hv_kvp_msg_enumerate kvp_data; -}; +} __attribute__((packed)); +#ifdef __KERNEL__#include <linux/scatterlist.h> #include <linux/list.h> #include <linux/uuid.h>
Signature · 1 line
1.7.4.1
PATCH 2/4 tools: hv: Use hyperv.h to get the KVP definitions
Now use hyperv.h to get the KVP defines in the KVP user-mode code.
--- tools/hv/hv_kvp_daemon.c | 28 +--------------------------- 1 files changed, 1 insertions(+), 27 deletions(-)
tools/hv/hv_kvp_daemon.c +1 -27
@@ -34,17 +34,12 @@#include <errno.h> #include <arpa/inet.h> #include <linux/connector.h> +#include <linux/hyperv.h> #include <linux/netlink.h> #include <ifaddrs.h> #include <netdb.h> #include <syslog.h> -/* -* -* The following definitions are shared with the in-kernel component; do not -* change any of this without making the corresponding changes in -* the KVP kernel component. -*/ /* * KVP protocol: The user mode component first registers with the
@@ -56,25 +51,8 @@* We use this infrastructure for also supporting queries from user mode * application for state that may be maintained in the KVP kernel component. * -* XXXKYS: Have a shared header file between the user and kernel (TODO) */ -enum kvp_op { -KVP_REGISTER =0 ,/* Register the user mode component*/ -KVP_KERNEL_GET ,/*Kernel is requesting the value for the specified key*/ -KVP_KERNEL_SET ,/*Kernel is providing the value for the specified key*/ -KVP_USER_GET ,/*User is requesting the value for the specified key*/ -KVP_USER_SET /*User is providing the value for the specified key*/ -}; - -#define HV_KVP_EXCHANGE_MAX_KEY_SIZE 512 -#define HV_KVP_EXCHANGE_MAX_VALUE_SIZE 2048 - -struct hv_ku_msg { -__u32 kvp_index; -__u8 kvp_key[HV_KVP_EXCHANGE_MAX_KEY_SIZE ];/* Key name */ -__u8 kvp_value[HV_KVP_EXCHANGE_MAX_VALUE_SIZE ];/* Key value */ -};enum key_index { FullyQualifiedDomainName =0 ,
@@ -89,10 +67,6 @@ enum key_index { ProcessorArchitecture }; -/* -* End of shared definitions. -*/ -static char kvp_send_buffer[4096 ];static char kvp_recv_buffer[4096 ];static struct sockaddr_nl addr;
Signature · 1 line
1.7.4.1
PATCH 3/4 drivers: hv: kvp: Cleanup the kernel/user protocol
In reply to K. Y. SrinivasanNow, cleanup the user/kernel KVP protocol by using the same structure definition that is used for host/guest KVP protocol. This simplifies the code.
--- drivers/hv/hv_kvp.c | 41 +++++++++++++++++++++++++---------------- include/linux/hyperv.h | 30 +++++------------------------- tools/hv/hv_kvp_daemon.c | 30 +++++++++++++++--------------- 3 files changed, 45 insertions(+), 56 deletions(-)
drivers/hv/hv_kvp.c +25 -16
@@ -71,15 +71,20 @@ kvp_register(void) {struct cn_msg *msg; +struct hv_kvp_msg *kvp_msg; +char *version; - msg =kzalloc (sizeof (*msg) +strlen (HV_DRV_VERSION ) +1 ,GFP_ATOMIC ); + msg =kzalloc (sizeof (*msg) +sizeof (struct hv_kvp_msg ),GFP_ATOMIC );if (msg) { + kvp_msg = (struct hv_kvp_msg *)msg->data; + version = kvp_msg->body.kvp_version; msg->id.idx =CN_KVP_IDX ; msg->id.val =CN_KVP_VAL ; - msg->seq =KVP_REGISTER ; -strcpy (msg->data,HV_DRV_VERSION ); - msg->len =strlen (HV_DRV_VERSION ) +1 ; + + kvp_msg->kvp_hdr.operation =KVP_OP_REGISTER ; +strcpy (version,HV_DRV_VERSION ); + msg->len =sizeof (struct hv_kvp_msg );cn_netlink_send (msg,0 ,GFP_ATOMIC );kfree (msg); }
@@ -101,23 +106,24 @@ kvp_work_func(struct work_struct *dummy)static void kvp_cn_callback (struct cn_msg *msg,struct netlink_skb_parms *nsp) { -struct hv_ku_msg *message; +struct hv_kvp_msg *message; +struct hv_kvp_msg_enumerate *data; - message = (struct hv_ku_msg *)msg->data; -if (msg->seq ==KVP_REGISTER ) { + message = (struct hv_kvp_msg *)msg->data; +if (message->kvp_hdr.operation ==KVP_OP_REGISTER ) {pr_info ("KVP: user-mode registering done.\n" );kvp_register (); } -if (msg->seq ==KVP_USER_SET ) { +if (message->kvp_hdr.operation ==KVP_OP_ENUMERATE ) { + data = &message->body.kvp_enum_data;/* * Complete the transaction by forwarding the key value * to the host. But first, cancel the timeout. */ if (cancel_delayed_work_sync (&kvp_work)) -kvp_respond_to_host (message->kvp_key, - message->kvp_value, - !strlen (message->kvp_key)); +kvp_respond_to_host (data->data.key, data->data.value, + !strlen (data->data.key)); } }
@@ -125,6 +131,7 @@ static void kvp_send_key(struct work_struct *dummy) {struct cn_msg *msg; +struct hv_kvp_msg *message;int index = kvp_transaction.index; msg =kzalloc (sizeof (*msg) +sizeof (struct hv_kvp_msg ) ,GFP_ATOMIC );
@@ -132,9 +139,11 @@ kvp_send_key(struct work_struct *dummy)if (msg) { msg->id.idx =CN_KVP_IDX ; msg->id.val =CN_KVP_VAL ; - msg->seq =KVP_KERNEL_GET ; - ((struct hv_ku_msg *)msg->data)->kvp_index = index; - msg->len =sizeof (struct hv_ku_msg ); + + message = (struct hv_kvp_msg *)msg->data; + message->kvp_hdr.operation =KVP_OP_ENUMERATE ; + message->body.kvp_enum_data.index = index; + msg->len =sizeof (struct hv_kvp_msg );cn_netlink_send (msg,0 ,GFP_ATOMIC );kfree (msg); }
@@ -191,7 +200,7 @@ kvp_respond_to_host(char *key, char *value, int error) kvp_msg = (struct hv_kvp_msg *) &recv_buffer[sizeof (struct vmbuspipe_hdr ) +sizeof (struct icmsg_hdr )]; - kvp_data = &kvp_msg->kvp_data; + kvp_data = &kvp_msg->body.kvp_enum_data; key_name = key;/*
@@ -266,7 +275,7 @@ void hv_kvp_onchannelcallback(void *context)sizeof (struct vmbuspipe_hdr ) + sizeof(struct icmsg_hdr)]; - kvp_data = &kvp_msg->kvp_data; + kvp_data = &kvp_msg->body.kvp_enum_data;/* * We only support the "get" operation on
include/linux/hyperv.h +5 -25
@@ -113,30 +113,6 @@* (not supported), a NULL key string is returned. */ -/* -* -* The following definitions are shared with the user-mode component; do not -* change any of this without making the corresponding changes in -* the KVP user-mode component. -*/ - -enum hv_ku_op { -KVP_REGISTER =0 ,/* Register the user mode component */ -KVP_KERNEL_GET ,/* Kernel is requesting the value */ -KVP_KERNEL_SET ,/* Kernel is providing the value */ -KVP_USER_GET ,/* User is requesting the value */ -KVP_USER_SET /* User is providing the value */ -}; - -struct hv_ku_msg { -__u32 kvp_index;/* Key index */ -__u8 kvp_key[HV_KVP_EXCHANGE_MAX_KEY_SIZE ];/* Key name */ -__u8 kvp_value[HV_KVP_EXCHANGE_MAX_VALUE_SIZE ];/* Key value */ -}; - - - -/* * Registry value types.
@@ -149,6 +125,7 @@ enum hv_kvp_exchg_op {KVP_OP_SET ,KVP_OP_DELETE ,KVP_OP_ENUMERATE , +KVP_OP_REGISTER , KVP_OP_COUNT /* Number of operations, must be last. */ };
@@ -182,7 +159,10 @@ struct hv_kvp_msg_enumerate {struct hv_kvp_msg {struct hv_kvp_hdr kvp_hdr; -struct hv_kvp_msg_enumerate kvp_data; +union { +struct hv_kvp_msg_enumerate kvp_enum_data; +char kvp_version[HV_KVP_EXCHANGE_MAX_KEY_SIZE ]; + } body; } __attribute__((packed));#ifdef __KERNEL__
tools/hv/hv_kvp_daemon.c +15 -15
@@ -302,7 +302,7 @@ int main(void)struct pollfd pfd;struct nlmsghdr *incoming_msg;struct cn_msg *incoming_cn_msg; -struct hv_ku_msg *hv_msg; +struct hv_kvp_msg *hv_msg;char *p;char *key_value;char *key_name;
@@ -340,9 +340,11 @@ int main(void) message = (struct cn_msg *)kvp_send_buffer; message->id.idx =CN_KVP_IDX ; message->id.val =CN_KVP_VAL ; - message->seq =KVP_REGISTER ; + + hv_msg = (struct hv_kvp_msg *)message->data; + hv_msg->kvp_hdr.operation =KVP_OP_REGISTER ; message->ack =0 ; - message->len =0 ; + message->len =sizeof (struct hv_kvp_msg ); len =netlink_send (fd, message);if (len <0 ) {
@@ -368,14 +370,15 @@ int main(void) incoming_msg = (struct nlmsghdr *)kvp_recv_buffer; incoming_cn_msg = (struct cn_msg *)NLMSG_DATA (incoming_msg); + hv_msg = (struct hv_kvp_msg *)incoming_cn_msg->data; -switch (incoming_cn_msg->seq) { -case KVP_REGISTER : +switch (hv_msg->kvp_hdr.operation) { +case KVP_OP_REGISTER :/* * Driver is registering with us; stash away the version * information. */ - p = (char *)incoming_cn_msg->data; + p = (char *)hv_msg->body.kvp_version; lic_version =malloc (strlen (p) +1 );if (lic_version) {strcpy (lic_version, p);
@@ -386,17 +389,15 @@ int main(void) }continue ; -case KVP_KERNEL_GET : -break ;default : -continue ; +break ; } - hv_msg = (struct hv_ku_msg *)incoming_cn_msg->data; - key_name = (char *)hv_msg->kvp_key; - key_value = (char *)hv_msg->kvp_value; + hv_msg = (struct hv_kvp_msg *)incoming_cn_msg->data; + key_name = (char *)hv_msg->body.kvp_enum_data.data.key; + key_value = (char *)hv_msg->body.kvp_enum_data.data.value; -switch (hv_msg->kvp_index) { +switch (hv_msg->body.kvp_enum_data.index) {case FullyQualifiedDomainName:kvp_get_domain_name (key_value,HV_KVP_EXCHANGE_MAX_VALUE_SIZE );
@@ -456,9 +457,8 @@ int main(void) incoming_cn_msg->id.idx =CN_KVP_IDX ; incoming_cn_msg->id.val =CN_KVP_VAL ; - incoming_cn_msg->seq =KVP_USER_SET ; incoming_cn_msg->ack =0 ; - incoming_cn_msg->len =sizeof (struct hv_ku_msg ); + incoming_cn_msg->len =sizeof (struct hv_kvp_msg ); len =netlink_send (fd, incoming_cn_msg);if (len <0 ) {
Signature · 1 line
1.7.4.1
PATCH 4/4 drivers: hv: Increase the number of VCPUs supported in the guest
In reply to K. Y. SrinivasanThe current code arbirarily limited the number of CPUs the guest could have. Change that so that we can support the maximum number of CPUs the guest can support. While we use NR_CPUS to size the per-cpu state all we are allocating based on NR_CPUS are the pointers to per-cpu state that will be allocatted in the context of the initializing CPU. This patch triggers a checkpatch warning for the usage of NR_CPU and since all we are allocating a couple of pointers per CPU, it should be ok.
--- drivers/hv/hv.c | 4 ++-- drivers/hv/hyperv_vmbus.h | 5 ++--- 2 files changed, 4 insertions(+), 5 deletions(-)
drivers/hv/hv.c +2 -2
@@ -155,9 +155,9 @@ int hv_init(void)union hv_x64_msr_hypercall_contents hypercall_msr;void *virtaddr =NULL ; -memset (hv_context.synic_event_page,0 ,sizeof (void *) *MAX_NUM_CPUS ); +memset (hv_context.synic_event_page,0 ,sizeof (void *) *NR_CPUS );memset (hv_context.synic_message_page,0 , -sizeof (void *) *MAX_NUM_CPUS ); +sizeof (void *) *NR_CPUS );if (!query_hypervisor_presence ()) goto cleanup;
drivers/hv/hyperv_vmbus.h +2 -3
@@ -457,7 +457,6 @@ static const uuid_le VMBUS_SERVICE_ID = { }, }; -#define MAX_NUM_CPUS 32struct hv_input_signal_event_buffer {
@@ -483,8 +482,8 @@ struct hv_context {/* 8-bytes aligned of the buffer above */ struct hv_input_signal_event *signal_event_param; -void *synic_message_page[MAX_NUM_CPUS ]; -void *synic_event_page[MAX_NUM_CPUS ]; +void *synic_message_page[NR_CPUS ]; +void *synic_event_page[NR_CPUS ]; };extern struct hv_context hv_context;
Signature · 1 line
1.7.4.1