Skip to contentSkip to conversation

drivers: hv

PATCH New K. Y. Srinivasan 1 participant 5 messages Feb 3, 2012

Subsystems (2)
lore
Share & tools
lore
#0 lore raw

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

#1 lore raw

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
index 7332b3f..b822978 100644
@@ -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
#2 lore raw

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
index 2b6a2d9..b75523c 100644
@@ -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
#3 lore raw

PATCH 3/4 drivers: hv: kvp: Cleanup the kernel/user protocol

In reply to K. Y. Srinivasan

Now, 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
index 4a6971e..0ef4c1f 100644
@@ -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
index b822978..75aee67 100644
@@ -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
index b75523c..4ebf703 100644
@@ -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
#4 lore raw

PATCH 4/4 drivers: hv: Increase the number of VCPUs supported in the guest

In reply to K. Y. Srinivasan

The 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
index 12aa97f..15956bd 100644
@@ -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
index 6d7d286..699f0d8 100644
@@ -457,7 +457,6 @@ static const uuid_le VMBUS_SERVICE_ID = {
 	},
 };
 
-#define MAX_NUM_CPUS	32
 
 
 struct 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