aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/hv
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/hv')
-rw-r--r--drivers/hv/channel_mgmt.c87
-rw-r--r--drivers/hv/hv.c4
-rw-r--r--drivers/hv/hv_kvp.c253
-rw-r--r--drivers/hv/hv_kvp.h184
-rw-r--r--drivers/hv/hv_util.c3
-rw-r--r--drivers/hv/hyperv_vmbus.h5
6 files changed, 193 insertions, 343 deletions
diff --git a/drivers/hv/channel_mgmt.c b/drivers/hv/channel_mgmt.c
index 36484db36baf..9ffbfc575a0c 100644
--- a/drivers/hv/channel_mgmt.c
+++ b/drivers/hv/channel_mgmt.c
@@ -37,81 +37,6 @@ struct vmbus_channel_message_table_entry {
37 void (*message_handler)(struct vmbus_channel_message_header *msg); 37 void (*message_handler)(struct vmbus_channel_message_header *msg);
38}; 38};
39 39
40#define MAX_MSG_TYPES 4
41#define MAX_NUM_DEVICE_CLASSES_SUPPORTED 8
42
43static const uuid_le
44 supported_device_classes[MAX_NUM_DEVICE_CLASSES_SUPPORTED] = {
45 /* {ba6163d9-04a1-4d29-b605-72e2ffb1dc7f} */
46 /* Storage - SCSI */
47 {
48 .b = {
49 0xd9, 0x63, 0x61, 0xba, 0xa1, 0x04, 0x29, 0x4d,
50 0xb6, 0x05, 0x72, 0xe2, 0xff, 0xb1, 0xdc, 0x7f
51 }
52 },
53
54 /* {F8615163-DF3E-46c5-913F-F2D2F965ED0E} */
55 /* Network */
56 {
57 .b = {
58 0x63, 0x51, 0x61, 0xF8, 0x3E, 0xDF, 0xc5, 0x46,
59 0x91, 0x3F, 0xF2, 0xD2, 0xF9, 0x65, 0xED, 0x0E
60 }
61 },
62
63 /* {CFA8B69E-5B4A-4cc0-B98B-8BA1A1F3F95A} */
64 /* Input */
65 {
66 .b = {
67 0x9E, 0xB6, 0xA8, 0xCF, 0x4A, 0x5B, 0xc0, 0x4c,
68 0xB9, 0x8B, 0x8B, 0xA1, 0xA1, 0xF3, 0xF9, 0x5A
69 }
70 },
71
72 /* {32412632-86cb-44a2-9b5c-50d1417354f5} */
73 /* IDE */
74 {
75 .b = {
76 0x32, 0x26, 0x41, 0x32, 0xcb, 0x86, 0xa2, 0x44,
77 0x9b, 0x5c, 0x50, 0xd1, 0x41, 0x73, 0x54, 0xf5
78 }
79 },
80 /* 0E0B6031-5213-4934-818B-38D90CED39DB */
81 /* Shutdown */
82 {
83 .b = {
84 0x31, 0x60, 0x0B, 0X0E, 0x13, 0x52, 0x34, 0x49,
85 0x81, 0x8B, 0x38, 0XD9, 0x0C, 0xED, 0x39, 0xDB
86 }
87 },
88 /* {9527E630-D0AE-497b-ADCE-E80AB0175CAF} */
89 /* TimeSync */
90 {
91 .b = {
92 0x30, 0xe6, 0x27, 0x95, 0xae, 0xd0, 0x7b, 0x49,
93 0xad, 0xce, 0xe8, 0x0a, 0xb0, 0x17, 0x5c, 0xaf
94 }
95 },
96 /* {57164f39-9115-4e78-ab55-382f3bd5422d} */
97 /* Heartbeat */
98 {
99 .b = {
100 0x39, 0x4f, 0x16, 0x57, 0x15, 0x91, 0x78, 0x4e,
101 0xab, 0x55, 0x38, 0x2f, 0x3b, 0xd5, 0x42, 0x2d
102 }
103 },
104 /* {A9A0F4E7-5A45-4d96-B827-8A841E8C03E6} */
105 /* KVP */
106 {
107 .b = {
108 0xe7, 0xf4, 0xa0, 0xa9, 0x45, 0x5a, 0x96, 0x4d,
109 0xb8, 0x27, 0x8a, 0x84, 0x1e, 0x8c, 0x3, 0xe6
110 }
111 },
112
113};
114
115 40
116/** 41/**
117 * vmbus_prep_negotiate_resp() - Create default response for Hyper-V Negotiate message 42 * vmbus_prep_negotiate_resp() - Create default response for Hyper-V Negotiate message
@@ -321,20 +246,8 @@ static void vmbus_onoffer(struct vmbus_channel_message_header *hdr)
321 struct vmbus_channel *newchannel; 246 struct vmbus_channel *newchannel;
322 uuid_le *guidtype; 247 uuid_le *guidtype;
323 uuid_le *guidinstance; 248 uuid_le *guidinstance;
324 int i;
325 int fsupported = 0;
326 249
327 offer = (struct vmbus_channel_offer_channel *)hdr; 250 offer = (struct vmbus_channel_offer_channel *)hdr;
328 for (i = 0; i < MAX_NUM_DEVICE_CLASSES_SUPPORTED; i++) {
329 if (!uuid_le_cmp(offer->offer.if_type,
330 supported_device_classes[i])) {
331 fsupported = 1;
332 break;
333 }
334 }
335
336 if (!fsupported)
337 return;
338 251
339 guidtype = &offer->offer.if_type; 252 guidtype = &offer->offer.if_type;
340 guidinstance = &offer->offer.if_instance; 253 guidinstance = &offer->offer.if_instance;
diff --git a/drivers/hv/hv.c b/drivers/hv/hv.c
index 12aa97f31f93..15956bd48b48 100644
--- a/drivers/hv/hv.c
+++ b/drivers/hv/hv.c
@@ -155,9 +155,9 @@ int hv_init(void)
155 union hv_x64_msr_hypercall_contents hypercall_msr; 155 union hv_x64_msr_hypercall_contents hypercall_msr;
156 void *virtaddr = NULL; 156 void *virtaddr = NULL;
157 157
158 memset(hv_context.synic_event_page, 0, sizeof(void *) * MAX_NUM_CPUS); 158 memset(hv_context.synic_event_page, 0, sizeof(void *) * NR_CPUS);
159 memset(hv_context.synic_message_page, 0, 159 memset(hv_context.synic_message_page, 0,
160 sizeof(void *) * MAX_NUM_CPUS); 160 sizeof(void *) * NR_CPUS);
161 161
162 if (!query_hypervisor_presence()) 162 if (!query_hypervisor_presence())
163 goto cleanup; 163 goto cleanup;
diff --git a/drivers/hv/hv_kvp.c b/drivers/hv/hv_kvp.c
index 0e8343f585bb..6186025209ce 100644
--- a/drivers/hv/hv_kvp.c
+++ b/drivers/hv/hv_kvp.c
@@ -28,8 +28,6 @@
28#include <linux/workqueue.h> 28#include <linux/workqueue.h>
29#include <linux/hyperv.h> 29#include <linux/hyperv.h>
30 30
31#include "hv_kvp.h"
32
33 31
34 32
35/* 33/*
@@ -44,9 +42,10 @@
44static struct { 42static struct {
45 bool active; /* transaction status - active or not */ 43 bool active; /* transaction status - active or not */
46 int recv_len; /* number of bytes received. */ 44 int recv_len; /* number of bytes received. */
47 int index; /* current index */ 45 struct hv_kvp_msg *kvp_msg; /* current message */
48 struct vmbus_channel *recv_channel; /* chn we got the request */ 46 struct vmbus_channel *recv_channel; /* chn we got the request */
49 u64 recv_req_id; /* request ID. */ 47 u64 recv_req_id; /* request ID. */
48 void *kvp_context; /* for the channel callback */
50} kvp_transaction; 49} kvp_transaction;
51 50
52static void kvp_send_key(struct work_struct *dummy); 51static void kvp_send_key(struct work_struct *dummy);
@@ -73,15 +72,20 @@ kvp_register(void)
73{ 72{
74 73
75 struct cn_msg *msg; 74 struct cn_msg *msg;
75 struct hv_kvp_msg *kvp_msg;
76 char *version;
76 77
77 msg = kzalloc(sizeof(*msg) + strlen(HV_DRV_VERSION) + 1 , GFP_ATOMIC); 78 msg = kzalloc(sizeof(*msg) + sizeof(struct hv_kvp_msg), GFP_ATOMIC);
78 79
79 if (msg) { 80 if (msg) {
81 kvp_msg = (struct hv_kvp_msg *)msg->data;
82 version = kvp_msg->body.kvp_register.version;
80 msg->id.idx = CN_KVP_IDX; 83 msg->id.idx = CN_KVP_IDX;
81 msg->id.val = CN_KVP_VAL; 84 msg->id.val = CN_KVP_VAL;
82 msg->seq = KVP_REGISTER; 85
83 strcpy(msg->data, HV_DRV_VERSION); 86 kvp_msg->kvp_hdr.operation = KVP_OP_REGISTER;
84 msg->len = strlen(HV_DRV_VERSION) + 1; 87 strcpy(version, HV_DRV_VERSION);
88 msg->len = sizeof(struct hv_kvp_msg);
85 cn_netlink_send(msg, 0, GFP_ATOMIC); 89 cn_netlink_send(msg, 0, GFP_ATOMIC);
86 kfree(msg); 90 kfree(msg);
87 } 91 }
@@ -103,23 +107,28 @@ kvp_work_func(struct work_struct *dummy)
103static void 107static void
104kvp_cn_callback(struct cn_msg *msg, struct netlink_skb_parms *nsp) 108kvp_cn_callback(struct cn_msg *msg, struct netlink_skb_parms *nsp)
105{ 109{
106 struct hv_ku_msg *message; 110 struct hv_kvp_msg *message;
111 struct hv_kvp_msg_enumerate *data;
107 112
108 message = (struct hv_ku_msg *)msg->data; 113 message = (struct hv_kvp_msg *)msg->data;
109 if (msg->seq == KVP_REGISTER) { 114 switch (message->kvp_hdr.operation) {
115 case KVP_OP_REGISTER:
110 pr_info("KVP: user-mode registering done.\n"); 116 pr_info("KVP: user-mode registering done.\n");
111 kvp_register(); 117 kvp_register();
112 } 118 kvp_transaction.active = false;
119 hv_kvp_onchannelcallback(kvp_transaction.kvp_context);
120 break;
113 121
114 if (msg->seq == KVP_USER_SET) { 122 default:
123 data = &message->body.kvp_enum_data;
115 /* 124 /*
116 * Complete the transaction by forwarding the key value 125 * Complete the transaction by forwarding the key value
117 * to the host. But first, cancel the timeout. 126 * to the host. But first, cancel the timeout.
118 */ 127 */
119 if (cancel_delayed_work_sync(&kvp_work)) 128 if (cancel_delayed_work_sync(&kvp_work))
120 kvp_respond_to_host(message->kvp_key, 129 kvp_respond_to_host(data->data.key,
121 message->kvp_value, 130 data->data.value,
122 !strlen(message->kvp_key)); 131 !strlen(data->data.key));
123 } 132 }
124} 133}
125 134
@@ -127,19 +136,105 @@ static void
127kvp_send_key(struct work_struct *dummy) 136kvp_send_key(struct work_struct *dummy)
128{ 137{
129 struct cn_msg *msg; 138 struct cn_msg *msg;
130 int index = kvp_transaction.index; 139 struct hv_kvp_msg *message;
140 struct hv_kvp_msg *in_msg;
141 __u8 operation = kvp_transaction.kvp_msg->kvp_hdr.operation;
142 __u8 pool = kvp_transaction.kvp_msg->kvp_hdr.pool;
143 __u32 val32;
144 __u64 val64;
131 145
132 msg = kzalloc(sizeof(*msg) + sizeof(struct hv_kvp_msg) , GFP_ATOMIC); 146 msg = kzalloc(sizeof(*msg) + sizeof(struct hv_kvp_msg) , GFP_ATOMIC);
147 if (!msg)
148 return;
133 149
134 if (msg) { 150 msg->id.idx = CN_KVP_IDX;
135 msg->id.idx = CN_KVP_IDX; 151 msg->id.val = CN_KVP_VAL;
136 msg->id.val = CN_KVP_VAL; 152
137 msg->seq = KVP_KERNEL_GET; 153 message = (struct hv_kvp_msg *)msg->data;
138 ((struct hv_ku_msg *)msg->data)->kvp_index = index; 154 message->kvp_hdr.operation = operation;
139 msg->len = sizeof(struct hv_ku_msg); 155 message->kvp_hdr.pool = pool;
140 cn_netlink_send(msg, 0, GFP_ATOMIC); 156 in_msg = kvp_transaction.kvp_msg;
141 kfree(msg); 157
158 /*
159 * The key/value strings sent from the host are encoded in
160 * in utf16; convert it to utf8 strings.
161 * The host assures us that the utf16 strings will not exceed
162 * the max lengths specified. We will however, reserve room
163 * for the string terminating character - in the utf16s_utf8s()
164 * function we limit the size of the buffer where the converted
165 * string is placed to HV_KVP_EXCHANGE_MAX_*_SIZE -1 to gaurantee
166 * that the strings can be properly terminated!
167 */
168
169 switch (message->kvp_hdr.operation) {
170 case KVP_OP_SET:
171 switch (in_msg->body.kvp_set.data.value_type) {
172 case REG_SZ:
173 /*
174 * The value is a string - utf16 encoding.
175 */
176 message->body.kvp_set.data.value_size =
177 utf16s_to_utf8s(
178 (wchar_t *)in_msg->body.kvp_set.data.value,
179 in_msg->body.kvp_set.data.value_size,
180 UTF16_LITTLE_ENDIAN,
181 message->body.kvp_set.data.value,
182 HV_KVP_EXCHANGE_MAX_VALUE_SIZE - 1) + 1;
183 break;
184
185 case REG_U32:
186 /*
187 * The value is a 32 bit scalar.
188 * We save this as a utf8 string.
189 */
190 val32 = in_msg->body.kvp_set.data.value_u32;
191 message->body.kvp_set.data.value_size =
192 sprintf(message->body.kvp_set.data.value,
193 "%d", val32) + 1;
194 break;
195
196 case REG_U64:
197 /*
198 * The value is a 64 bit scalar.
199 * We save this as a utf8 string.
200 */
201 val64 = in_msg->body.kvp_set.data.value_u64;
202 message->body.kvp_set.data.value_size =
203 sprintf(message->body.kvp_set.data.value,
204 "%llu", val64) + 1;
205 break;
206
207 }
208 case KVP_OP_GET:
209 message->body.kvp_set.data.key_size =
210 utf16s_to_utf8s(
211 (wchar_t *)in_msg->body.kvp_set.data.key,
212 in_msg->body.kvp_set.data.key_size,
213 UTF16_LITTLE_ENDIAN,
214 message->body.kvp_set.data.key,
215 HV_KVP_EXCHANGE_MAX_KEY_SIZE - 1) + 1;
216 break;
217
218 case KVP_OP_DELETE:
219 message->body.kvp_delete.key_size =
220 utf16s_to_utf8s(
221 (wchar_t *)in_msg->body.kvp_delete.key,
222 in_msg->body.kvp_delete.key_size,
223 UTF16_LITTLE_ENDIAN,
224 message->body.kvp_delete.key,
225 HV_KVP_EXCHANGE_MAX_KEY_SIZE - 1) + 1;
226 break;
227
228 case KVP_OP_ENUMERATE:
229 message->body.kvp_enum_data.index =
230 in_msg->body.kvp_enum_data.index;
231 break;
142 } 232 }
233
234 msg->len = sizeof(struct hv_kvp_msg);
235 cn_netlink_send(msg, 0, GFP_ATOMIC);
236 kfree(msg);
237
143 return; 238 return;
144} 239}
145 240
@@ -151,10 +246,11 @@ static void
151kvp_respond_to_host(char *key, char *value, int error) 246kvp_respond_to_host(char *key, char *value, int error)
152{ 247{
153 struct hv_kvp_msg *kvp_msg; 248 struct hv_kvp_msg *kvp_msg;
154 struct hv_kvp_msg_enumerate *kvp_data; 249 struct hv_kvp_exchg_msg_value *kvp_data;
155 char *key_name; 250 char *key_name;
156 struct icmsg_hdr *icmsghdrp; 251 struct icmsg_hdr *icmsghdrp;
157 int keylen, valuelen; 252 int keylen = 0;
253 int valuelen = 0;
158 u32 buf_len; 254 u32 buf_len;
159 struct vmbus_channel *channel; 255 struct vmbus_channel *channel;
160 u64 req_id; 256 u64 req_id;
@@ -181,6 +277,9 @@ kvp_respond_to_host(char *key, char *value, int error)
181 277
182 kvp_transaction.active = false; 278 kvp_transaction.active = false;
183 279
280 icmsghdrp = (struct icmsg_hdr *)
281 &recv_buffer[sizeof(struct vmbuspipe_hdr)];
282
184 if (channel->onchannel_callback == NULL) 283 if (channel->onchannel_callback == NULL)
185 /* 284 /*
186 * We have raced with util driver being unloaded; 285 * We have raced with util driver being unloaded;
@@ -188,41 +287,67 @@ kvp_respond_to_host(char *key, char *value, int error)
188 */ 287 */
189 return; 288 return;
190 289
191 icmsghdrp = (struct icmsg_hdr *)
192 &recv_buffer[sizeof(struct vmbuspipe_hdr)];
193 kvp_msg = (struct hv_kvp_msg *)
194 &recv_buffer[sizeof(struct vmbuspipe_hdr) +
195 sizeof(struct icmsg_hdr)];
196 kvp_data = &kvp_msg->kvp_data;
197 key_name = key;
198 290
199 /* 291 /*
200 * If the error parameter is set, terminate the host's enumeration. 292 * If the error parameter is set, terminate the host's enumeration
293 * on this pool.
201 */ 294 */
202 if (error) { 295 if (error) {
203 /* 296 /*
204 * We don't support this index or the we have timedout; 297 * Something failed or the we have timedout;
205 * terminate the host-side iteration by returning an error. 298 * terminate the current host-side iteration.
206 */ 299 */
207 icmsghdrp->status = HV_E_FAIL; 300 icmsghdrp->status = HV_S_CONT;
208 goto response_done; 301 goto response_done;
209 } 302 }
210 303
304 icmsghdrp->status = HV_S_OK;
305
306 kvp_msg = (struct hv_kvp_msg *)
307 &recv_buffer[sizeof(struct vmbuspipe_hdr) +
308 sizeof(struct icmsg_hdr)];
309
310 switch (kvp_transaction.kvp_msg->kvp_hdr.operation) {
311 case KVP_OP_GET:
312 kvp_data = &kvp_msg->body.kvp_get.data;
313 goto copy_value;
314
315 case KVP_OP_SET:
316 case KVP_OP_DELETE:
317 goto response_done;
318
319 default:
320 break;
321 }
322
323 kvp_data = &kvp_msg->body.kvp_enum_data.data;
324 key_name = key;
325
211 /* 326 /*
212 * The windows host expects the key/value pair to be encoded 327 * The windows host expects the key/value pair to be encoded
213 * in utf16. 328 * in utf16. Ensure that the key/value size reported to the host
329 * will be less than or equal to the MAX size (including the
330 * terminating character).
214 */ 331 */
215 keylen = utf8s_to_utf16s(key_name, strlen(key_name), UTF16_HOST_ENDIAN, 332 keylen = utf8s_to_utf16s(key_name, strlen(key_name), UTF16_HOST_ENDIAN,
216 (wchar_t *) kvp_data->data.key, 333 (wchar_t *) kvp_data->key,
217 HV_KVP_EXCHANGE_MAX_KEY_SIZE / 2); 334 (HV_KVP_EXCHANGE_MAX_KEY_SIZE / 2) - 2);
218 kvp_data->data.key_size = 2*(keylen + 1); /* utf16 encoding */ 335 kvp_data->key_size = 2*(keylen + 1); /* utf16 encoding */
336
337copy_value:
219 valuelen = utf8s_to_utf16s(value, strlen(value), UTF16_HOST_ENDIAN, 338 valuelen = utf8s_to_utf16s(value, strlen(value), UTF16_HOST_ENDIAN,
220 (wchar_t *) kvp_data->data.value, 339 (wchar_t *) kvp_data->value,
221 HV_KVP_EXCHANGE_MAX_VALUE_SIZE / 2); 340 (HV_KVP_EXCHANGE_MAX_VALUE_SIZE / 2) - 2);
222 kvp_data->data.value_size = 2*(valuelen + 1); /* utf16 encoding */ 341 kvp_data->value_size = 2*(valuelen + 1); /* utf16 encoding */
223 342
224 kvp_data->data.value_type = REG_SZ; /* all our values are strings */ 343 /*
225 icmsghdrp->status = HV_S_OK; 344 * If the utf8s to utf16s conversion failed; notify host
345 * of the error.
346 */
347 if ((keylen < 0) || (valuelen < 0))
348 icmsghdrp->status = HV_E_FAIL;
349
350 kvp_data->value_type = REG_SZ; /* all our values are strings */
226 351
227response_done: 352response_done:
228 icmsghdrp->icflags = ICMSGHDRFLAG_TRANSACTION | ICMSGHDRFLAG_RESPONSE; 353 icmsghdrp->icflags = ICMSGHDRFLAG_TRANSACTION | ICMSGHDRFLAG_RESPONSE;
@@ -249,11 +374,18 @@ void hv_kvp_onchannelcallback(void *context)
249 u64 requestid; 374 u64 requestid;
250 375
251 struct hv_kvp_msg *kvp_msg; 376 struct hv_kvp_msg *kvp_msg;
252 struct hv_kvp_msg_enumerate *kvp_data;
253 377
254 struct icmsg_hdr *icmsghdrp; 378 struct icmsg_hdr *icmsghdrp;
255 struct icmsg_negotiate *negop = NULL; 379 struct icmsg_negotiate *negop = NULL;
256 380
381 if (kvp_transaction.active) {
382 /*
383 * We will defer processing this callback once
384 * the current transaction is complete.
385 */
386 kvp_transaction.kvp_context = context;
387 return;
388 }
257 389
258 vmbus_recvpacket(channel, recv_buffer, PAGE_SIZE, &recvlen, &requestid); 390 vmbus_recvpacket(channel, recv_buffer, PAGE_SIZE, &recvlen, &requestid);
259 391
@@ -268,29 +400,16 @@ void hv_kvp_onchannelcallback(void *context)
268 sizeof(struct vmbuspipe_hdr) + 400 sizeof(struct vmbuspipe_hdr) +
269 sizeof(struct icmsg_hdr)]; 401 sizeof(struct icmsg_hdr)];
270 402
271 kvp_data = &kvp_msg->kvp_data;
272
273 /*
274 * We only support the "get" operation on
275 * "KVP_POOL_AUTO" pool.
276 */
277
278 if ((kvp_msg->kvp_hdr.pool != KVP_POOL_AUTO) ||
279 (kvp_msg->kvp_hdr.operation !=
280 KVP_OP_ENUMERATE)) {
281 icmsghdrp->status = HV_E_FAIL;
282 goto callback_done;
283 }
284
285 /* 403 /*
286 * Stash away this global state for completing the 404 * Stash away this global state for completing the
287 * transaction; note transactions are serialized. 405 * transaction; note transactions are serialized.
288 */ 406 */
407
289 kvp_transaction.recv_len = recvlen; 408 kvp_transaction.recv_len = recvlen;
290 kvp_transaction.recv_channel = channel; 409 kvp_transaction.recv_channel = channel;
291 kvp_transaction.recv_req_id = requestid; 410 kvp_transaction.recv_req_id = requestid;
292 kvp_transaction.active = true; 411 kvp_transaction.active = true;
293 kvp_transaction.index = kvp_data->index; 412 kvp_transaction.kvp_msg = kvp_msg;
294 413
295 /* 414 /*
296 * Get the information from the 415 * Get the information from the
@@ -308,8 +427,6 @@ void hv_kvp_onchannelcallback(void *context)
308 427
309 } 428 }
310 429
311callback_done:
312
313 icmsghdrp->icflags = ICMSGHDRFLAG_TRANSACTION 430 icmsghdrp->icflags = ICMSGHDRFLAG_TRANSACTION
314 | ICMSGHDRFLAG_RESPONSE; 431 | ICMSGHDRFLAG_RESPONSE;
315 432
@@ -330,6 +447,14 @@ hv_kvp_init(struct hv_util_service *srv)
330 return err; 447 return err;
331 recv_buffer = srv->recv_buffer; 448 recv_buffer = srv->recv_buffer;
332 449
450 /*
451 * When this driver loads, the user level daemon that
452 * processes the host requests may not yet be running.
453 * Defer processing channel callbacks until the daemon
454 * has registered.
455 */
456 kvp_transaction.active = true;
457
333 return 0; 458 return 0;
334} 459}
335 460
diff --git a/drivers/hv/hv_kvp.h b/drivers/hv/hv_kvp.h
deleted file mode 100644
index 9b765d7df838..000000000000
--- a/drivers/hv/hv_kvp.h
+++ /dev/null
@@ -1,184 +0,0 @@
1/*
2 * An implementation of HyperV key value pair (KVP) functionality for Linux.
3 *
4 *
5 * Copyright (C) 2010, Novell, Inc.
6 * Author : K. Y. Srinivasan <ksrinivasan@novell.com>
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License version 2 as published
10 * by the Free Software Foundation.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
15 * NON INFRINGEMENT. See the GNU General Public License for more
16 * details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
21 *
22 */
23#ifndef _KVP_H
24#define _KVP_H_
25
26/*
27 * Maximum value size - used for both key names and value data, and includes
28 * any applicable NULL terminators.
29 *
30 * Note: This limit is somewhat arbitrary, but falls easily within what is
31 * supported for all native guests (back to Win 2000) and what is reasonable
32 * for the IC KVP exchange functionality. Note that Windows Me/98/95 are
33 * limited to 255 character key names.
34 *
35 * MSDN recommends not storing data values larger than 2048 bytes in the
36 * registry.
37 *
38 * Note: This value is used in defining the KVP exchange message - this value
39 * cannot be modified without affecting the message size and compatibility.
40 */
41
42/*
43 * bytes, including any null terminators
44 */
45#define HV_KVP_EXCHANGE_MAX_VALUE_SIZE (2048)
46
47
48/*
49 * Maximum key size - the registry limit for the length of an entry name
50 * is 256 characters, including the null terminator
51 */
52
53#define HV_KVP_EXCHANGE_MAX_KEY_SIZE (512)
54
55/*
56 * In Linux, we implement the KVP functionality in two components:
57 * 1) The kernel component which is packaged as part of the hv_utils driver
58 * is responsible for communicating with the host and responsible for
59 * implementing the host/guest protocol. 2) A user level daemon that is
60 * responsible for data gathering.
61 *
62 * Host/Guest Protocol: The host iterates over an index and expects the guest
63 * to assign a key name to the index and also return the value corresponding to
64 * the key. The host will have atmost one KVP transaction outstanding at any
65 * given point in time. The host side iteration stops when the guest returns
66 * an error. Microsoft has specified the following mapping of key names to
67 * host specified index:
68 *
69 * Index Key Name
70 * 0 FullyQualifiedDomainName
71 * 1 IntegrationServicesVersion
72 * 2 NetworkAddressIPv4
73 * 3 NetworkAddressIPv6
74 * 4 OSBuildNumber
75 * 5 OSName
76 * 6 OSMajorVersion
77 * 7 OSMinorVersion
78 * 8 OSVersion
79 * 9 ProcessorArchitecture
80 *
81 * The Windows host expects the Key Name and Key Value to be encoded in utf16.
82 *
83 * Guest Kernel/KVP Daemon Protocol: As noted earlier, we implement all of the
84 * data gathering functionality in a user mode daemon. The user level daemon
85 * is also responsible for binding the key name to the index as well. The
86 * kernel and user-level daemon communicate using a connector channel.
87 *
88 * The user mode component first registers with the
89 * the kernel component. Subsequently, the kernel component requests, data
90 * for the specified keys. In response to this message the user mode component
91 * fills in the value corresponding to the specified key. We overload the
92 * sequence field in the cn_msg header to define our KVP message types.
93 *
94 *
95 * The kernel component simply acts as a conduit for communication between the
96 * Windows host and the user-level daemon. The kernel component passes up the
97 * index received from the Host to the user-level daemon. If the index is
98 * valid (supported), the corresponding key as well as its
99 * value (both are strings) is returned. If the index is invalid
100 * (not supported), a NULL key string is returned.
101 */
102
103/*
104 *
105 * The following definitions are shared with the user-mode component; do not
106 * change any of this without making the corresponding changes in
107 * the KVP user-mode component.
108 */
109
110#define CN_KVP_VAL 0x1 /* This supports queries from the kernel */
111#define CN_KVP_USER_VAL 0x2 /* This supports queries from the user */
112
113enum hv_ku_op {
114 KVP_REGISTER = 0, /* Register the user mode component */
115 KVP_KERNEL_GET, /* Kernel is requesting the value */
116 KVP_KERNEL_SET, /* Kernel is providing the value */
117 KVP_USER_GET, /* User is requesting the value */
118 KVP_USER_SET /* User is providing the value */
119};
120
121struct hv_ku_msg {
122 __u32 kvp_index; /* Key index */
123 __u8 kvp_key[HV_KVP_EXCHANGE_MAX_KEY_SIZE]; /* Key name */
124 __u8 kvp_value[HV_KVP_EXCHANGE_MAX_VALUE_SIZE]; /* Key value */
125};
126
127
128
129
130#ifdef __KERNEL__
131
132/*
133 * Registry value types.
134 */
135
136#define REG_SZ 1
137
138enum hv_kvp_exchg_op {
139 KVP_OP_GET = 0,
140 KVP_OP_SET,
141 KVP_OP_DELETE,
142 KVP_OP_ENUMERATE,
143 KVP_OP_COUNT /* Number of operations, must be last. */
144};
145
146enum hv_kvp_exchg_pool {
147 KVP_POOL_EXTERNAL = 0,
148 KVP_POOL_GUEST,
149 KVP_POOL_AUTO,
150 KVP_POOL_AUTO_EXTERNAL,
151 KVP_POOL_AUTO_INTERNAL,
152 KVP_POOL_COUNT /* Number of pools, must be last. */
153};
154
155struct hv_kvp_hdr {
156 u8 operation;
157 u8 pool;
158};
159
160struct hv_kvp_exchg_msg_value {
161 u32 value_type;
162 u32 key_size;
163 u32 value_size;
164 u8 key[HV_KVP_EXCHANGE_MAX_KEY_SIZE];
165 u8 value[HV_KVP_EXCHANGE_MAX_VALUE_SIZE];
166};
167
168struct hv_kvp_msg_enumerate {
169 u32 index;
170 struct hv_kvp_exchg_msg_value data;
171};
172
173struct hv_kvp_msg {
174 struct hv_kvp_hdr kvp_hdr;
175 struct hv_kvp_msg_enumerate kvp_data;
176};
177
178int hv_kvp_init(struct hv_util_service *);
179void hv_kvp_deinit(void);
180void hv_kvp_onchannelcallback(void *);
181
182#endif /* __KERNEL__ */
183#endif /* _KVP_H */
184
diff --git a/drivers/hv/hv_util.c b/drivers/hv/hv_util.c
index 55d58f21e6d4..dbb8b8eec210 100644
--- a/drivers/hv/hv_util.c
+++ b/drivers/hv/hv_util.c
@@ -28,9 +28,6 @@
28#include <linux/reboot.h> 28#include <linux/reboot.h>
29#include <linux/hyperv.h> 29#include <linux/hyperv.h>
30 30
31#include "hv_kvp.h"
32
33
34static void shutdown_onchannelcallback(void *context); 31static void shutdown_onchannelcallback(void *context);
35static struct hv_util_service util_shutdown = { 32static struct hv_util_service util_shutdown = {
36 .util_cb = shutdown_onchannelcallback, 33 .util_cb = shutdown_onchannelcallback,
diff --git a/drivers/hv/hyperv_vmbus.h b/drivers/hv/hyperv_vmbus.h
index 6d7d286d5440..699f0d8e59ed 100644
--- a/drivers/hv/hyperv_vmbus.h
+++ b/drivers/hv/hyperv_vmbus.h
@@ -457,7 +457,6 @@ static const uuid_le VMBUS_SERVICE_ID = {
457 }, 457 },
458}; 458};
459 459
460#define MAX_NUM_CPUS 32
461 460
462 461
463struct hv_input_signal_event_buffer { 462struct hv_input_signal_event_buffer {
@@ -483,8 +482,8 @@ struct hv_context {
483 /* 8-bytes aligned of the buffer above */ 482 /* 8-bytes aligned of the buffer above */
484 struct hv_input_signal_event *signal_event_param; 483 struct hv_input_signal_event *signal_event_param;
485 484
486 void *synic_message_page[MAX_NUM_CPUS]; 485 void *synic_message_page[NR_CPUS];
487 void *synic_event_page[MAX_NUM_CPUS]; 486 void *synic_event_page[NR_CPUS];
488}; 487};
489 488
490extern struct hv_context hv_context; 489extern struct hv_context hv_context;