Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F81970634
D8280.id21644.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
14 KB
Referenced Files
None
Subscribers
None
D8280.id21644.diff
View Options
Index: head/sys/dev/hyperv/utilities/hv_heartbeat.c
===================================================================
--- head/sys/dev/hyperv/utilities/hv_heartbeat.c
+++ head/sys/dev/hyperv/utilities/hv_heartbeat.c
@@ -40,6 +40,14 @@
#include "vmbus_if.h"
+#define VMBUS_HEARTBEAT_FWVER_MAJOR 3
+#define VMBUS_HEARTBEAT_FWVER \
+ VMBUS_IC_VERSION(VMBUS_HEARTBEAT_FWVER_MAJOR, 0)
+
+#define VMBUS_HEARTBEAT_MSGVER_MAJOR 3
+#define VMBUS_HEARTBEAT_MSGVER \
+ VMBUS_IC_VERSION(VMBUS_HEARTBEAT_MSGVER_MAJOR, 0)
+
static const struct vmbus_ic_desc vmbus_heartbeat_descs[] = {
{
.ic_guid = { .hv_guid = {
@@ -80,7 +88,8 @@
*/
switch (hdr->ic_type) {
case VMBUS_ICMSG_TYPE_NEGOTIATE:
- error = vmbus_ic_negomsg(sc, data, &dlen);
+ error = vmbus_ic_negomsg(sc, data, &dlen,
+ VMBUS_HEARTBEAT_FWVER, VMBUS_HEARTBEAT_MSGVER);
if (error)
return;
break;
Index: head/sys/dev/hyperv/utilities/hv_kvp.h
===================================================================
--- head/sys/dev/hyperv/utilities/hv_kvp.h
+++ head/sys/dev/hyperv/utilities/hv_kvp.h
@@ -28,7 +28,6 @@
#ifndef _KVP_H
#define _KVP_H
-
/*
* An implementation of HyperV key value pair (KVP) functionality for FreeBSD
*
@@ -178,9 +177,9 @@
}__attribute__((packed));
struct hv_kvp_hdr {
- uint8_t operation;
- uint8_t pool;
- uint16_t pad;
+ uint8_t operation;
+ uint8_t pool;
+ uint16_t pad;
} __attribute__((packed));
struct hv_kvp_exchg_msg_value {
Index: head/sys/dev/hyperv/utilities/hv_kvp.c
===================================================================
--- head/sys/dev/hyperv/utilities/hv_kvp.c
+++ head/sys/dev/hyperv/utilities/hv_kvp.c
@@ -61,7 +61,9 @@
#include <sys/mutex.h>
#include <dev/hyperv/include/hyperv.h>
+#include <dev/hyperv/include/vmbus.h>
#include <dev/hyperv/utilities/hv_utilreg.h>
+#include <dev/hyperv/utilities/vmbus_icreg.h>
#include "hv_util.h"
#include "unicode.h"
@@ -74,6 +76,12 @@
#define KVP_ERROR 1
#define kvp_hdr hdr.kvp_hdr
+#define KVP_FWVER_MAJOR 3
+#define KVP_FWVER VMBUS_IC_VERSION(KVP_FWVER_MAJOR, 0)
+
+#define KVP_MSGVER_MAJOR 4
+#define KVP_MSGVER VMBUS_IC_VERSION(KVP_MSGVER_MAJOR, 0)
+
/* hv_kvp debug control */
static int hv_kvp_log = 0;
@@ -208,52 +216,10 @@
sc->host_msg_id = request_id;
sc->rcv_buf = rcv_buf;
sc->host_kvp_msg = (struct hv_kvp_msg *)&rcv_buf[
- sizeof(struct hv_vmbus_pipe_hdr) +
- sizeof(struct hv_vmbus_icmsg_hdr)];
+ sizeof(struct hv_vmbus_pipe_hdr) +
+ sizeof(struct hv_vmbus_icmsg_hdr)];
}
-
-/*
- * hv_kvp - version neogtiation function
- */
-static void
-hv_kvp_negotiate_version(struct hv_vmbus_icmsg_hdr *icmsghdrp, uint8_t *buf)
-{
- struct hv_vmbus_icmsg_negotiate *negop;
- int icframe_vercnt;
- int icmsg_vercnt;
-
- icmsghdrp->icmsgsize = 0x10;
-
- negop = (struct hv_vmbus_icmsg_negotiate *)&buf[
- sizeof(struct hv_vmbus_pipe_hdr) +
- sizeof(struct hv_vmbus_icmsg_hdr)];
- icframe_vercnt = negop->icframe_vercnt;
- icmsg_vercnt = negop->icmsg_vercnt;
-
- /*
- * Select the framework version number we will support
- */
- if ((icframe_vercnt >= 2) && (negop->icversion_data[1].major == 3)) {
- icframe_vercnt = 3;
- if (icmsg_vercnt > 2)
- icmsg_vercnt = 4;
- else
- icmsg_vercnt = 3;
- } else {
- icframe_vercnt = 1;
- icmsg_vercnt = 1;
- }
-
- negop->icframe_vercnt = 1;
- negop->icmsg_vercnt = 1;
- negop->icversion_data[0].major = icframe_vercnt;
- negop->icversion_data[0].minor = 0;
- negop->icversion_data[1].major = icmsg_vercnt;
- negop->icversion_data[1].minor = 0;
-}
-
-
/*
* Convert ip related info in umsg from utf8 to utf16 and store in hmsg
*/
@@ -578,7 +544,8 @@
error = HV_KVP_E_FAIL;
hv_icmsg_hdrp->status = error;
- hv_icmsg_hdrp->icflags = HV_ICMSGHDRFLAG_TRANSACTION | HV_ICMSGHDRFLAG_RESPONSE;
+ hv_icmsg_hdrp->icflags = HV_ICMSGHDRFLAG_TRANSACTION |
+ HV_ICMSGHDRFLAG_RESPONSE;
error = vmbus_chan_send(vmbus_get_channel(sc->dev),
VMBUS_CHANPKT_TYPE_INBAND, 0, sc->rcv_buf, sc->host_msg_len,
@@ -622,8 +589,8 @@
uint32_t recvlen = 0;
uint64_t requestid;
struct hv_vmbus_icmsg_hdr *icmsghdrp;
- int ret = 0;
- hv_kvp_sc *sc;
+ int ret = 0, error;
+ hv_kvp_sc *sc;
hv_kvp_log_info("%s: entering hv_kvp_process_request\n", __func__);
@@ -637,14 +604,15 @@
/* XXX check recvlen to make sure that it contains enough data */
while ((ret == 0) && (recvlen > 0)) {
-
icmsghdrp = (struct hv_vmbus_icmsg_hdr *)
- &kvp_buf[sizeof(struct hv_vmbus_pipe_hdr)];
+ &kvp_buf[sizeof(struct hv_vmbus_pipe_hdr)];
hv_kvp_transaction_init(sc, recvlen, requestid, kvp_buf);
if (icmsghdrp->icmsgtype == HV_ICMSGTYPE_NEGOTIATE) {
- hv_kvp_negotiate_version(icmsghdrp, kvp_buf);
- hv_kvp_respond_host(sc, ret);
+ error = vmbus_ic_negomsg(&sc->util_sc,
+ kvp_buf, &recvlen, KVP_FWVER, KVP_MSGVER);
+ /* XXX handle vmbus_ic_negomsg failure. */
+ hv_kvp_respond_host(sc, error);
/*
* It is ok to not acquire the mutex before setting
Index: head/sys/dev/hyperv/utilities/hv_shutdown.c
===================================================================
--- head/sys/dev/hyperv/utilities/hv_shutdown.c
+++ head/sys/dev/hyperv/utilities/hv_shutdown.c
@@ -41,6 +41,14 @@
#include "vmbus_if.h"
+#define VMBUS_SHUTDOWN_FWVER_MAJOR 3
+#define VMBUS_SHUTDOWN_FWVER \
+ VMBUS_IC_VERSION(VMBUS_SHUTDOWN_FWVER_MAJOR, 0)
+
+#define VMBUS_SHUTDOWN_MSGVER_MAJOR 3
+#define VMBUS_SHUTDOWN_MSGVER \
+ VMBUS_IC_VERSION(VMBUS_SHUTDOWN_MSGVER_MAJOR, 0)
+
static const struct vmbus_ic_desc vmbus_shutdown_descs[] = {
{
.ic_guid = { .hv_guid = {
@@ -82,7 +90,8 @@
*/
switch (hdr->ic_type) {
case VMBUS_ICMSG_TYPE_NEGOTIATE:
- error = vmbus_ic_negomsg(sc, data, &dlen);
+ error = vmbus_ic_negomsg(sc, data, &dlen,
+ VMBUS_SHUTDOWN_FWVER, VMBUS_SHUTDOWN_MSGVER);
if (error)
return;
break;
Index: head/sys/dev/hyperv/utilities/hv_timesync.c
===================================================================
--- head/sys/dev/hyperv/utilities/hv_timesync.c
+++ head/sys/dev/hyperv/utilities/hv_timesync.c
@@ -42,6 +42,14 @@
#include "vmbus_if.h"
+#define VMBUS_TIMESYNC_FWVER_MAJOR 3
+#define VMBUS_TIMESYNC_FWVER \
+ VMBUS_IC_VERSION(VMBUS_TIMESYNC_FWVER_MAJOR, 0)
+
+#define VMBUS_TIMESYNC_MSGVER_MAJOR 3
+#define VMBUS_TIMESYNC_MSGVER \
+ VMBUS_IC_VERSION(VMBUS_TIMESYNC_MSGVER_MAJOR, 0)
+
static const struct vmbus_ic_desc vmbus_timesync_descs[] = {
{
.ic_guid = { .hv_guid = {
@@ -162,7 +170,8 @@
*/
switch (hdr->ic_type) {
case VMBUS_ICMSG_TYPE_NEGOTIATE:
- error = vmbus_ic_negomsg(sc, data, &dlen);
+ error = vmbus_ic_negomsg(sc, data, &dlen,
+ VMBUS_TIMESYNC_FWVER, VMBUS_TIMESYNC_MSGVER);
if (error)
return;
break;
Index: head/sys/dev/hyperv/utilities/hv_util.h
===================================================================
--- head/sys/dev/hyperv/utilities/hv_util.h
+++ head/sys/dev/hyperv/utilities/hv_util.h
@@ -42,6 +42,8 @@
device_t ic_dev;
uint8_t *receive_buffer;
int ic_buflen;
+ uint32_t ic_fwver; /* framework version */
+ uint32_t ic_msgver; /* message version */
} hv_util_sc;
struct vmbus_ic_desc {
@@ -54,6 +56,7 @@
int hv_util_attach(device_t dev, vmbus_chan_callback_t cb);
int hv_util_detach(device_t dev);
int vmbus_ic_probe(device_t dev, const struct vmbus_ic_desc descs[]);
-int vmbus_ic_negomsg(struct hv_util_sc *, void *data, int *dlen);
+int vmbus_ic_negomsg(struct hv_util_sc *sc, void *data, int *dlen,
+ uint32_t fw_ver, uint32_t msg_ver);
#endif
Index: head/sys/dev/hyperv/utilities/hv_util.c
===================================================================
--- head/sys/dev/hyperv/utilities/hv_util.c
+++ head/sys/dev/hyperv/utilities/hv_util.c
@@ -37,6 +37,7 @@
#include <sys/module.h>
#include <sys/reboot.h>
#include <sys/systm.h>
+#include <sys/sysctl.h>
#include <sys/timetc.h>
#include <dev/hyperv/include/hyperv.h>
@@ -53,52 +54,145 @@
__offsetof(struct vmbus_icmsg_negotiate, ic_ver[VMBUS_IC_VERCNT])
CTASSERT(VMBUS_IC_NEGOSZ < VMBUS_IC_BRSIZE);
+static int vmbus_ic_fwver_sysctl(SYSCTL_HANDLER_ARGS);
+static int vmbus_ic_msgver_sysctl(SYSCTL_HANDLER_ARGS);
+
int
-vmbus_ic_negomsg(struct hv_util_sc *sc, void *data, int *dlen0)
+vmbus_ic_negomsg(struct hv_util_sc *sc, void *data, int *dlen0,
+ uint32_t fw_ver, uint32_t msg_ver)
{
struct vmbus_icmsg_negotiate *nego;
- int cnt, major, dlen = *dlen0;
+ int i, cnt, dlen = *dlen0, error;
+ uint32_t sel_fw_ver, sel_msg_ver;
+ bool has_fw_ver, has_msg_ver;
/*
- * Preliminary message size verification
+ * Preliminary message verification.
*/
if (dlen < sizeof(*nego)) {
device_printf(sc->ic_dev, "truncated ic negotiate, len %d\n",
dlen);
- return EINVAL;
+ return (EINVAL);
}
nego = data;
+ if (nego->ic_fwver_cnt == 0) {
+ device_printf(sc->ic_dev, "ic negotiate does not contain "
+ "framework version %u\n", nego->ic_fwver_cnt);
+ return (EINVAL);
+ }
+ if (nego->ic_msgver_cnt == 0) {
+ device_printf(sc->ic_dev, "ic negotiate does not contain "
+ "message version %u\n", nego->ic_msgver_cnt);
+ return (EINVAL);
+ }
+
cnt = nego->ic_fwver_cnt + nego->ic_msgver_cnt;
if (dlen < __offsetof(struct vmbus_icmsg_negotiate, ic_ver[cnt])) {
device_printf(sc->ic_dev, "ic negotiate does not contain "
"versions %d\n", dlen);
- return EINVAL;
+ return (EINVAL);
+ }
+
+ error = EOPNOTSUPP;
+
+ /*
+ * Find the best match framework version.
+ */
+ has_fw_ver = false;
+ for (i = 0; i < nego->ic_fwver_cnt; ++i) {
+ if (VMBUS_ICVER_LE(nego->ic_ver[i], fw_ver)) {
+ if (!has_fw_ver) {
+ sel_fw_ver = nego->ic_ver[i];
+ has_fw_ver = true;
+ } else if (VMBUS_ICVER_GT(nego->ic_ver[i],
+ sel_fw_ver)) {
+ sel_fw_ver = nego->ic_ver[i];
+ }
+ }
+ }
+ if (!has_fw_ver) {
+ device_printf(sc->ic_dev, "failed to select framework "
+ "version\n");
+ goto done;
+ }
+
+ /*
+ * Fine the best match message version.
+ */
+ has_msg_ver = false;
+ for (i = nego->ic_fwver_cnt;
+ i < nego->ic_fwver_cnt + nego->ic_msgver_cnt; ++i) {
+ if (VMBUS_ICVER_LE(nego->ic_ver[i], msg_ver)) {
+ if (!has_msg_ver) {
+ sel_msg_ver = nego->ic_ver[i];
+ has_msg_ver = true;
+ } else if (VMBUS_ICVER_GT(nego->ic_ver[i],
+ sel_msg_ver)) {
+ sel_msg_ver = nego->ic_ver[i];
+ }
+ }
+ }
+ if (!has_msg_ver) {
+ device_printf(sc->ic_dev, "failed to select message "
+ "version\n");
+ goto done;
}
- /* Select major version; XXX looks wrong. */
- if (nego->ic_fwver_cnt >= 2 && VMBUS_ICVER_MAJOR(nego->ic_ver[1]) == 3)
- major = 3;
- else
- major = 1;
+ error = 0;
+done:
+ if (bootverbose || !has_fw_ver || !has_msg_ver) {
+ if (has_fw_ver) {
+ device_printf(sc->ic_dev, "sel framework version: "
+ "%u.%u\n",
+ VMBUS_ICVER_MAJOR(sel_fw_ver),
+ VMBUS_ICVER_MINOR(sel_fw_ver));
+ }
+ for (i = 0; i < nego->ic_fwver_cnt; i++) {
+ device_printf(sc->ic_dev, "supp framework version: "
+ "%u.%u\n",
+ VMBUS_ICVER_MAJOR(nego->ic_ver[i]),
+ VMBUS_ICVER_MINOR(nego->ic_ver[i]));
+ }
+
+ if (has_msg_ver) {
+ device_printf(sc->ic_dev, "sel message version: "
+ "%u.%u\n",
+ VMBUS_ICVER_MAJOR(sel_msg_ver),
+ VMBUS_ICVER_MINOR(sel_msg_ver));
+ }
+ for (i = nego->ic_fwver_cnt;
+ i < nego->ic_fwver_cnt + nego->ic_msgver_cnt; i++) {
+ device_printf(sc->ic_dev, "supp message version: "
+ "%u.%u\n",
+ VMBUS_ICVER_MAJOR(nego->ic_ver[i]),
+ VMBUS_ICVER_MINOR(nego->ic_ver[i]));
+ }
+ }
+ if (error)
+ return (error);
+
+ /* Record the selected versions. */
+ sc->ic_fwver = sel_fw_ver;
+ sc->ic_msgver = sel_msg_ver;
- /* One framework version */
+ /* One framework version. */
nego->ic_fwver_cnt = 1;
- nego->ic_ver[0] = VMBUS_IC_VERSION(major, 0);
+ nego->ic_ver[0] = sel_fw_ver;
- /* One message version */
+ /* One message version. */
nego->ic_msgver_cnt = 1;
- nego->ic_ver[1] = VMBUS_IC_VERSION(major, 0);
+ nego->ic_ver[1] = sel_msg_ver;
- /* Update data size */
+ /* Update data size. */
nego->ic_hdr.ic_dsize = VMBUS_IC_NEGOSZ -
sizeof(struct vmbus_icmsg_hdr);
- /* Update total size, if necessary */
+ /* Update total size, if necessary. */
if (dlen < VMBUS_IC_NEGOSZ)
*dlen0 = VMBUS_IC_NEGOSZ;
- return 0;
+ return (0);
}
int
@@ -124,6 +218,8 @@
{
struct hv_util_sc *sc = device_get_softc(dev);
struct vmbus_channel *chan = vmbus_get_channel(dev);
+ struct sysctl_oid_list *child;
+ struct sysctl_ctx_list *ctx;
int error;
sc->ic_dev = dev;
@@ -146,9 +242,41 @@
free(sc->receive_buffer, M_DEVBUF);
return (error);
}
+
+ ctx = device_get_sysctl_ctx(dev);
+ child = SYSCTL_CHILDREN(device_get_sysctl_tree(dev));
+ SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "fw_version",
+ CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_MPSAFE, sc, 0,
+ vmbus_ic_fwver_sysctl, "A", "framework version");
+ SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "msg_version",
+ CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_MPSAFE, sc, 0,
+ vmbus_ic_msgver_sysctl, "A", "message version");
+
return (0);
}
+static int
+vmbus_ic_fwver_sysctl(SYSCTL_HANDLER_ARGS)
+{
+ struct hv_util_sc *sc = arg1;
+ char verstr[16];
+
+ snprintf(verstr, sizeof(verstr), "%u.%u",
+ VMBUS_ICVER_MAJOR(sc->ic_fwver), VMBUS_ICVER_MINOR(sc->ic_fwver));
+ return sysctl_handle_string(oidp, verstr, sizeof(verstr), req);
+}
+
+static int
+vmbus_ic_msgver_sysctl(SYSCTL_HANDLER_ARGS)
+{
+ struct hv_util_sc *sc = arg1;
+ char verstr[16];
+
+ snprintf(verstr, sizeof(verstr), "%u.%u",
+ VMBUS_ICVER_MAJOR(sc->ic_msgver), VMBUS_ICVER_MINOR(sc->ic_msgver));
+ return sysctl_handle_string(oidp, verstr, sizeof(verstr), req);
+}
+
int
hv_util_detach(device_t dev)
{
Index: head/sys/dev/hyperv/utilities/hv_utilreg.h
===================================================================
--- head/sys/dev/hyperv/utilities/hv_utilreg.h
+++ head/sys/dev/hyperv/utilities/hv_utilreg.h
@@ -76,16 +76,4 @@
hv_vmbus_ic_version icversion_data[1]; /* any size array */
} __packed hv_vmbus_icmsg_negotiate;
-typedef struct hv_vmbus_shutdown_msg_data {
- uint32_t reason_code;
- uint32_t timeout_seconds;
- uint32_t flags;
- uint8_t display_message[2048];
-} __packed hv_vmbus_shutdown_msg_data;
-
-typedef struct hv_vmbus_heartbeat_msg_data {
- uint64_t seq_num;
- uint32_t reserved[8];
-} __packed hv_vmbus_heartbeat_msg_data;
-
#endif /* !_HV_UTILREG_H_ */
Index: head/sys/dev/hyperv/utilities/vmbus_icreg.h
===================================================================
--- head/sys/dev/hyperv/utilities/vmbus_icreg.h
+++ head/sys/dev/hyperv/utilities/vmbus_icreg.h
@@ -42,6 +42,12 @@
#define VMBUS_IC_VERSION(major, minor) ((major) | (((uint32_t)(minor)) << 16))
#define VMBUS_ICVER_MAJOR(ver) ((ver) & 0xffff)
#define VMBUS_ICVER_MINOR(ver) (((ver) & 0xffff0000) >> 16)
+#define VMBUS_ICVER_SWAP(ver) \
+ ((VMBUS_ICVER_MAJOR((ver)) << 16) | VMBUS_ICVER_MINOR((ver)))
+#define VMBUS_ICVER_LE(v1, v2) \
+ (VMBUS_ICVER_SWAP((v1)) <= VMBUS_ICVER_SWAP((v2)))
+#define VMBUS_ICVER_GT(v1, v2) \
+ (VMBUS_ICVER_SWAP((v1)) > VMBUS_ICVER_SWAP((v2)))
struct vmbus_pipe_hdr {
uint32_t ph_flags;
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sun, Dec 15, 7:40 PM (19 h, 52 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
9091827
Default Alt Text
D8280.id21644.diff (14 KB)
Attached To
Mode
D8280: hyperv/util unify the negotitation for utils
Attached
Detach File
Event Timeline
Log In to Comment