blob: 5286919645cc387fff05efff483c7870b45ee922 [file] [log] [blame] [raw]
10.3-RELEASE vs. 10.3-RELEASE-p20.
diff -ru --exclude-from freebsd-src-diff-exclude-names /var/tmp/freebsd-src/usr/src/sys/amd64/amd64/sys_machdep.c freebsd-10.3/usr/src/sys/amd64/amd64/sys_machdep.c
--- /var/tmp/freebsd-src/usr/src/sys/amd64/amd64/sys_machdep.c 2016-03-25 09:09:25.000000000 +0800
+++ freebsd-10.3/usr/src/sys/amd64/amd64/sys_machdep.c 2017-07-24 12:45:00.426453461 +0800
@@ -617,6 +617,8 @@
largest_ld = uap->start + uap->num;
if (largest_ld > max_ldt_segment)
largest_ld = max_ldt_segment;
+ if (largest_ld < uap->start)
+ return (EINVAL);
i = largest_ld - uap->start;
mtx_lock(&dt_lock);
bzero(&((struct user_segment_descriptor *)(pldt->ldt_base))
@@ -629,7 +631,8 @@
/* verify range of descriptors to modify */
largest_ld = uap->start + uap->num;
if (uap->start >= max_ldt_segment ||
- largest_ld > max_ldt_segment)
+ largest_ld > max_ldt_segment ||
+ largest_ld < uap->start)
return (EINVAL);
}
diff -ru --exclude-from freebsd-src-diff-exclude-names /var/tmp/freebsd-src/usr/src/sys/cam/ata/ata_xpt.c freebsd-10.3/usr/src/sys/cam/ata/ata_xpt.c
--- /var/tmp/freebsd-src/usr/src/sys/cam/ata/ata_xpt.c 2016-03-25 09:09:43.000000000 +0800
+++ freebsd-10.3/usr/src/sys/cam/ata/ata_xpt.c 2017-07-24 14:04:44.514125030 +0800
@@ -40,6 +40,7 @@
#include <sys/interrupt.h>
#include <sys/sbuf.h>
+#include <sys/eventhandler.h>
#include <sys/lock.h>
#include <sys/mutex.h>
#include <sys/sysctl.h>
@@ -827,12 +828,18 @@
{
struct ccb_pathinq cpi;
int16_t *ptr;
+ int veto = 0;
ident_buf = &softc->ident_data;
for (ptr = (int16_t *)ident_buf;
ptr < (int16_t *)ident_buf + sizeof(struct ata_params)/2; ptr++) {
*ptr = le16toh(*ptr);
}
+ EVENTHANDLER_INVOKE(ada_probe_veto, path, ident_buf, &veto);
+ if (veto) {
+ goto device_fail;
+ }
+
if (strncmp(ident_buf->model, "FX", 2) &&
strncmp(ident_buf->model, "NEC", 3) &&
strncmp(ident_buf->model, "Pioneer", 7) &&
diff -ru --exclude-from freebsd-src-diff-exclude-names /var/tmp/freebsd-src/usr/src/sys/cddl/compat/opensolaris/kern/opensolaris_uio.c freebsd-10.3/usr/src/sys/cddl/compat/opensolaris/kern/opensolaris_uio.c
--- /var/tmp/freebsd-src/usr/src/sys/cddl/compat/opensolaris/kern/opensolaris_uio.c 2016-03-25 09:09:27.000000000 +0800
+++ freebsd-10.3/usr/src/sys/cddl/compat/opensolaris/kern/opensolaris_uio.c 2018-01-14 00:05:33.900254376 +0800
@@ -103,7 +103,8 @@
uiop->uio_iovcnt--;
continue;
}
- iovp->iov_base += niovb;
+ //iovp->iov_base += niovb;
+ iovp->iov_base = (char *)iovp->iov_base + niovb;
uiop->uio_loffset += niovb;
iovp->iov_len -= niovb;
uiop->uio_resid -= niovb;
diff -ru --exclude-from freebsd-src-diff-exclude-names /var/tmp/freebsd-src/usr/src/sys/cddl/compat/opensolaris/kern/opensolaris_vfs.c freebsd-10.3/usr/src/sys/cddl/compat/opensolaris/kern/opensolaris_vfs.c
--- /var/tmp/freebsd-src/usr/src/sys/cddl/compat/opensolaris/kern/opensolaris_vfs.c 2016-03-25 09:09:27.000000000 +0800
+++ freebsd-10.3/usr/src/sys/cddl/compat/opensolaris/kern/opensolaris_vfs.c 2017-07-24 12:45:00.432452955 +0800
@@ -196,6 +196,7 @@
VI_UNLOCK(vp);
vrele(vp);
vfs_unbusy(mp);
+ vfs_freeopts(mp->mnt_optnew);
vfs_mount_destroy(mp);
*vpp = NULL;
return (error);
diff -ru --exclude-from freebsd-src-diff-exclude-names /var/tmp/freebsd-src/usr/src/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_send.c freebsd-10.3/usr/src/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_send.c
--- /var/tmp/freebsd-src/usr/src/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_send.c 2016-03-25 09:09:27.000000000 +0800
+++ freebsd-10.3/usr/src/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_send.c 2018-01-14 00:06:44.913249033 +0800
@@ -1807,7 +1807,7 @@
while (done < len) {
ssize_t resid;
- ra->err = restore_bytes(ra, buf + done,
+ ra->err = restore_bytes(ra, (char *)buf + done,
len - done, ra->voff, &resid);
if (resid == len - done) {
diff -ru --exclude-from freebsd-src-diff-exclude-names /var/tmp/freebsd-src/usr/src/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_acl.c freebsd-10.3/usr/src/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_acl.c
--- /var/tmp/freebsd-src/usr/src/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_acl.c 2016-03-25 09:09:27.000000000 +0800
+++ freebsd-10.3/usr/src/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_acl.c 2018-11-05 20:14:30.687611396 +0800
@@ -2367,7 +2367,9 @@
int error;
int is_attr;
boolean_t check_privs;
+#ifndef __FreeBSD_kernel__
znode_t *xzp;
+#endif
znode_t *check_zp = zp;
mode_t needed_bits;
uid_t owner;
@@ -2443,15 +2445,19 @@
if ((error = zfs_zaccess_common(check_zp, mode, &working_mode,
&check_privs, skipaclchk, cr)) == 0) {
+#ifndef __FreeBSD_kernel__
if (is_attr)
VN_RELE(ZTOV(xzp));
+#endif
return (secpolicy_vnode_access2(cr, ZTOV(zp), owner,
needed_bits, needed_bits));
}
if (error && !check_privs) {
+#ifndef __FreeBSD_kernel__
if (is_attr)
VN_RELE(ZTOV(xzp));
+#endif
return (error);
}
@@ -2512,9 +2518,10 @@
needed_bits, needed_bits);
}
-
+#ifndef __FreeBSD_kernel__
if (is_attr)
VN_RELE(ZTOV(xzp));
+#endif
return (error);
}
diff -ru --exclude-from freebsd-src-diff-exclude-names /var/tmp/freebsd-src/usr/src/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c freebsd-10.3/usr/src/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c
--- /var/tmp/freebsd-src/usr/src/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c 2016-03-25 09:09:27.000000000 +0800
+++ freebsd-10.3/usr/src/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c 2018-01-14 23:16:11.409504373 +0800
@@ -2741,7 +2741,8 @@
*ncookies -= ncooks;
if (uio->uio_segflg == UIO_SYSSPACE && uio->uio_iovcnt == 1) {
- iovp->iov_base += outcount;
+ //iovp->iov_base += outcount;
+ iovp->iov_base = (char *)iovp->iov_base + outcount;
iovp->iov_len -= outcount;
uio->uio_resid -= outcount;
} else if (error = uiomove(outbuf, (long)outcount, UIO_READ, uio)) {
diff -ru --exclude-from freebsd-src-diff-exclude-names /var/tmp/freebsd-src/usr/src/sys/compat/linux/linux_ioctl.c freebsd-10.3/usr/src/sys/compat/linux/linux_ioctl.c
--- /var/tmp/freebsd-src/usr/src/sys/compat/linux/linux_ioctl.c 2016-03-25 09:09:43.000000000 +0800
+++ freebsd-10.3/usr/src/sys/compat/linux/linux_ioctl.c 2017-07-24 12:45:00.437453092 +0800
@@ -915,6 +915,8 @@
case LINUX_TIOCGSERIAL: {
struct linux_serial_struct lss;
+
+ bzero(&lss, sizeof(lss));
lss.type = LINUX_PORT_16550A;
lss.flags = 0;
lss.close_delay = 0;
diff -ru --exclude-from freebsd-src-diff-exclude-names /var/tmp/freebsd-src/usr/src/sys/compat/linux/linux_misc.c freebsd-10.3/usr/src/sys/compat/linux/linux_misc.c
--- /var/tmp/freebsd-src/usr/src/sys/compat/linux/linux_misc.c 2016-03-25 09:09:43.000000000 +0800
+++ freebsd-10.3/usr/src/sys/compat/linux/linux_misc.c 2017-07-24 12:45:00.442453454 +0800
@@ -150,6 +150,7 @@
int i, j;
struct timespec ts;
+ bzero(&sysinfo, sizeof(sysinfo));
getnanouptime(&ts);
if (ts.tv_nsec != 0)
ts.tv_sec++;
diff -ru --exclude-from freebsd-src-diff-exclude-names /var/tmp/freebsd-src/usr/src/sys/conf/files.amd64 freebsd-10.3/usr/src/sys/conf/files.amd64
--- /var/tmp/freebsd-src/usr/src/sys/conf/files.amd64 2016-03-25 09:09:25.000000000 +0800
+++ freebsd-10.3/usr/src/sys/conf/files.amd64 2017-07-24 14:04:44.562126016 +0800
@@ -262,7 +262,6 @@
dev/hyperv/netvsc/hv_net_vsc.c optional hyperv
dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c optional hyperv
dev/hyperv/netvsc/hv_rndis_filter.c optional hyperv
-dev/hyperv/stordisengage/hv_ata_pci_disengage.c optional hyperv
dev/hyperv/storvsc/hv_storvsc_drv_freebsd.c optional hyperv
dev/hyperv/utilities/hv_kvp.c optional hyperv
dev/hyperv/utilities/hv_util.c optional hyperv
diff -ru --exclude-from freebsd-src-diff-exclude-names /var/tmp/freebsd-src/usr/src/sys/conf/files.i386 freebsd-10.3/usr/src/sys/conf/files.i386
--- /var/tmp/freebsd-src/usr/src/sys/conf/files.i386 2016-03-25 09:09:25.000000000 +0800
+++ freebsd-10.3/usr/src/sys/conf/files.i386 2017-07-24 14:04:44.599123863 +0800
@@ -240,7 +240,6 @@
dev/hyperv/netvsc/hv_net_vsc.c optional hyperv
dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c optional hyperv
dev/hyperv/netvsc/hv_rndis_filter.c optional hyperv
-dev/hyperv/stordisengage/hv_ata_pci_disengage.c optional hyperv
dev/hyperv/storvsc/hv_storvsc_drv_freebsd.c optional hyperv
dev/hyperv/utilities/hv_kvp.c optional hyperv
dev/hyperv/utilities/hv_util.c optional hyperv
diff -ru --exclude-from freebsd-src-diff-exclude-names /var/tmp/freebsd-src/usr/src/sys/conf/newvers.sh freebsd-10.3/usr/src/sys/conf/newvers.sh
--- /var/tmp/freebsd-src/usr/src/sys/conf/newvers.sh 2016-03-25 09:09:25.000000000 +0800
+++ freebsd-10.3/usr/src/sys/conf/newvers.sh 2017-07-24 14:04:44.627124914 +0800
@@ -32,7 +32,7 @@
TYPE="FreeBSD"
REVISION="10.3"
-BRANCH="RELEASE"
+BRANCH="RELEASE-p20"
if [ "X${BRANCH_OVERRIDE}" != "X" ]; then
BRANCH=${BRANCH_OVERRIDE}
fi
diff -ru --exclude-from freebsd-src-diff-exclude-names /var/tmp/freebsd-src/usr/src/sys/contrib/ipfilter/netinet/ip_frag.c freebsd-10.3/usr/src/sys/contrib/ipfilter/netinet/ip_frag.c
--- /var/tmp/freebsd-src/usr/src/sys/contrib/ipfilter/netinet/ip_frag.c 2016-03-25 09:09:47.000000000 +0800
+++ freebsd-10.3/usr/src/sys/contrib/ipfilter/netinet/ip_frag.c 2017-07-24 14:04:44.653122031 +0800
@@ -456,7 +456,7 @@
IPFR_CMPSZ)) {
RWLOCK_EXIT(lock);
FBUMPD(ifs_exists);
- KFREE(fra);
+ KFREE(fran);
return NULL;
}
diff -ru --exclude-from freebsd-src-diff-exclude-names /var/tmp/freebsd-src/usr/src/sys/dev/hyperv/include/hyperv.h freebsd-10.3/usr/src/sys/dev/hyperv/include/hyperv.h
--- /var/tmp/freebsd-src/usr/src/sys/dev/hyperv/include/hyperv.h 2016-03-25 09:09:30.000000000 +0800
+++ freebsd-10.3/usr/src/sys/dev/hyperv/include/hyperv.h 2017-07-24 14:04:44.658123792 +0800
@@ -124,6 +124,8 @@
unsigned char data[16];
} __packed hv_guid;
+int snprintf_hv_guid(char *, size_t, const hv_guid *);
+
#define HV_NIC_GUID \
.data = {0x63, 0x51, 0x61, 0xF8, 0x3E, 0xDF, 0xc5, 0x46, \
0x91, 0x3F, 0xF2, 0xD2, 0xF9, 0x65, 0xED, 0x0E}
diff -ru --exclude-from freebsd-src-diff-exclude-names /var/tmp/freebsd-src/usr/src/sys/dev/hyperv/storvsc/hv_storvsc_drv_freebsd.c freebsd-10.3/usr/src/sys/dev/hyperv/storvsc/hv_storvsc_drv_freebsd.c
--- /var/tmp/freebsd-src/usr/src/sys/dev/hyperv/storvsc/hv_storvsc_drv_freebsd.c 2016-03-25 09:09:30.000000000 +0800
+++ freebsd-10.3/usr/src/sys/dev/hyperv/storvsc/hv_storvsc_drv_freebsd.c 2017-07-24 14:04:44.690124986 +0800
@@ -58,6 +58,7 @@
#include <sys/lock.h>
#include <sys/sema.h>
#include <sys/sglist.h>
+#include <sys/eventhandler.h>
#include <machine/bus.h>
#include <sys/bus_dma.h>
@@ -81,12 +82,6 @@
#define BLKVSC_MAX_IO_REQUESTS STORVSC_MAX_IO_REQUESTS
#define STORVSC_MAX_TARGETS (2)
-#define STORVSC_WIN7_MAJOR 4
-#define STORVSC_WIN7_MINOR 2
-
-#define STORVSC_WIN8_MAJOR 5
-#define STORVSC_WIN8_MINOR 1
-
#define VSTOR_PKT_SIZE (sizeof(struct vstor_packet) - vmscsi_size_delta)
#define HV_ALIGN(x, a) roundup2(x, a)
@@ -204,11 +199,12 @@
STORVSC_RINGBUFFER_SIZE}
};
+static eventhandler_tag storvsc_handler_tag;
/*
* Sense buffer size changed in win8; have a run-time
* variable to track the size we should use.
*/
-static int sense_buffer_size;
+static int sense_buffer_size = PRE_WIN8_STORVSC_SENSE_BUFFER_SIZE;
/*
* The size of the vmscsi_request has changed in win8. The
@@ -218,9 +214,46 @@
* Track the correct size we need to apply.
*/
static int vmscsi_size_delta;
+/*
+ * The storage protocol version is determined during the
+ * initial exchange with the host. It will indicate which
+ * storage functionality is available in the host.
+*/
+static int vmstor_proto_version;
+
+struct vmstor_proto {
+ int proto_version;
+ int sense_buffer_size;
+ int vmscsi_size_delta;
+};
-static int storvsc_current_major;
-static int storvsc_current_minor;
+static const struct vmstor_proto vmstor_proto_list[] = {
+ {
+ VMSTOR_PROTOCOL_VERSION_WIN10,
+ POST_WIN7_STORVSC_SENSE_BUFFER_SIZE,
+ 0
+ },
+ {
+ VMSTOR_PROTOCOL_VERSION_WIN8_1,
+ POST_WIN7_STORVSC_SENSE_BUFFER_SIZE,
+ 0
+ },
+ {
+ VMSTOR_PROTOCOL_VERSION_WIN8,
+ POST_WIN7_STORVSC_SENSE_BUFFER_SIZE,
+ 0
+ },
+ {
+ VMSTOR_PROTOCOL_VERSION_WIN7,
+ PRE_WIN8_STORVSC_SENSE_BUFFER_SIZE,
+ sizeof(struct vmscsi_win8_extension),
+ },
+ {
+ VMSTOR_PROTOCOL_VERSION_WIN6,
+ PRE_WIN8_STORVSC_SENSE_BUFFER_SIZE,
+ sizeof(struct vmscsi_win8_extension),
+ }
+};
/* static functions */
static int storvsc_probe(device_t dev);
@@ -435,7 +468,7 @@
static int
hv_storvsc_channel_init(struct hv_device *dev)
{
- int ret = 0;
+ int ret = 0, i;
struct hv_storvsc_request *request;
struct vstor_packet *vstor_packet;
struct storvsc_softc *sc;
@@ -484,19 +517,20 @@
goto cleanup;
}
- /* reuse the packet for version range supported */
+ for (i = 0; i < nitems(vmstor_proto_list); i++) {
+ /* reuse the packet for version range supported */
- memset(vstor_packet, 0, sizeof(struct vstor_packet));
- vstor_packet->operation = VSTOR_OPERATION_QUERYPROTOCOLVERSION;
- vstor_packet->flags = REQUEST_COMPLETION_FLAG;
+ memset(vstor_packet, 0, sizeof(struct vstor_packet));
+ vstor_packet->operation = VSTOR_OPERATION_QUERYPROTOCOLVERSION;
+ vstor_packet->flags = REQUEST_COMPLETION_FLAG;
- vstor_packet->u.version.major_minor =
- VMSTOR_PROTOCOL_VERSION(storvsc_current_major, storvsc_current_minor);
+ vstor_packet->u.version.major_minor =
+ vmstor_proto_list[i].proto_version;
- /* revision is only significant for Windows guests */
- vstor_packet->u.version.revision = 0;
+ /* revision is only significant for Windows guests */
+ vstor_packet->u.version.revision = 0;
- ret = hv_vmbus_channel_send_packet(
+ ret = hv_vmbus_channel_send_packet(
dev->channel,
vstor_packet,
VSTOR_PKT_SIZE,
@@ -504,20 +538,34 @@
HV_VMBUS_PACKET_TYPE_DATA_IN_BAND,
HV_VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
- if (ret != 0)
- goto cleanup;
+ if (ret != 0)
+ goto cleanup;
- /* wait 5 seconds */
- ret = sema_timedwait(&request->synch_sema, 5 * hz);
+ /* wait 5 seconds */
+ ret = sema_timedwait(&request->synch_sema, 5 * hz);
- if (ret)
- goto cleanup;
+ if (ret)
+ goto cleanup;
- /* TODO: Check returned version */
- if (vstor_packet->operation != VSTOR_OPERATION_COMPLETEIO ||
- vstor_packet->status != 0)
- goto cleanup;
+ if (vstor_packet->operation != VSTOR_OPERATION_COMPLETEIO) {
+ ret = EINVAL;
+ goto cleanup;
+ }
+ if (vstor_packet->status == 0) {
+ vmstor_proto_version =
+ vmstor_proto_list[i].proto_version;
+ sense_buffer_size =
+ vmstor_proto_list[i].sense_buffer_size;
+ vmscsi_size_delta =
+ vmstor_proto_list[i].vmscsi_size_delta;
+ break;
+ }
+ }
+ if (vstor_packet->status != 0) {
+ ret = EINVAL;
+ goto cleanup;
+ }
/**
* Query channel properties
*/
@@ -767,6 +815,14 @@
vm_srb = &vstor_packet->u.vm_srb;
+ /*
+ * Copy some fields of the host's response into the request structure,
+ * because the fields will be used later in storvsc_io_done().
+ */
+ request->vstor_packet.u.vm_srb.scsi_status = vm_srb->scsi_status;
+ request->vstor_packet.u.vm_srb.srb_status = vm_srb->srb_status;
+ request->vstor_packet.u.vm_srb.transfer_len = vm_srb->transfer_len;
+
if (((vm_srb->scsi_status & 0xFF) == SCSI_STATUS_CHECK_COND) &&
(vm_srb->srb_status & SRB_STATUS_AUTOSENSE_VALID)) {
/* Autosense data available */
@@ -913,33 +969,13 @@
static int
storvsc_probe(device_t dev)
{
- int ata_disk_enable = 0;
int ret = ENXIO;
- if (hv_vmbus_protocal_version == HV_VMBUS_VERSION_WS2008 ||
- hv_vmbus_protocal_version == HV_VMBUS_VERSION_WIN7) {
- sense_buffer_size = PRE_WIN8_STORVSC_SENSE_BUFFER_SIZE;
- vmscsi_size_delta = sizeof(struct vmscsi_win8_extension);
- storvsc_current_major = STORVSC_WIN7_MAJOR;
- storvsc_current_minor = STORVSC_WIN7_MINOR;
- } else {
- sense_buffer_size = POST_WIN7_STORVSC_SENSE_BUFFER_SIZE;
- vmscsi_size_delta = 0;
- storvsc_current_major = STORVSC_WIN8_MAJOR;
- storvsc_current_minor = STORVSC_WIN8_MINOR;
- }
-
switch (storvsc_get_storage_type(dev)) {
case DRIVER_BLKVSC:
if(bootverbose)
- device_printf(dev, "DRIVER_BLKVSC-Emulated ATA/IDE probe\n");
- if (!getenv_int("hw.ata.disk_enable", &ata_disk_enable)) {
- if(bootverbose)
- device_printf(dev,
- "Enlightened ATA/IDE detected\n");
- ret = BUS_PROBE_DEFAULT;
- } else if(bootverbose)
- device_printf(dev, "Emulated ATA/IDE set (hw.ata.disk_enable set)\n");
+ device_printf(dev, "Enlightened ATA/IDE detected\n");
+ ret = BUS_PROBE_DEFAULT;
break;
case DRIVER_STORVSC:
if(bootverbose)
@@ -1273,6 +1309,7 @@
}
#endif /* HVS_TIMEOUT_TEST */
+#ifdef notyet
/**
* @brief timeout handler for requests
*
@@ -1320,6 +1357,7 @@
storvsc_timeout_test(reqp, MODE_SELECT_10, 1);
#endif
}
+#endif
/**
* @brief StorVSC device poll function
@@ -1472,6 +1510,7 @@
return;
}
+#ifdef notyet
if (ccb->ccb_h.timeout != CAM_TIME_INFINITY) {
callout_init(&reqp->callout, CALLOUT_MPSAFE);
callout_reset_sbt(&reqp->callout,
@@ -1491,6 +1530,7 @@
}
#endif /* HVS_TIMEOUT_TEST */
}
+#endif
if ((res = hv_storvsc_io_request(sc->hs_dev, reqp)) != 0) {
xpt_print(ccb->ccb_h.path,
@@ -1923,66 +1963,17 @@
return(0);
}
-/*
- * Modified based on scsi_print_inquiry which is responsible to
- * print the detail information for scsi_inquiry_data.
- *
- * Return 1 if it is valid, 0 otherwise.
- */
-static inline int
-is_inquiry_valid(const struct scsi_inquiry_data *inq_data)
+static uint32_t
+is_scsi_valid(const struct scsi_inquiry_data *inq_data)
{
- uint8_t type;
- char vendor[16], product[48], revision[16];
-
- /*
- * Check device type and qualifier
- */
- if (!(SID_QUAL_IS_VENDOR_UNIQUE(inq_data) ||
- SID_QUAL(inq_data) == SID_QUAL_LU_CONNECTED))
- return (0);
-
+ u_int8_t type;
type = SID_TYPE(inq_data);
- switch (type) {
- case T_DIRECT:
- case T_SEQUENTIAL:
- case T_PRINTER:
- case T_PROCESSOR:
- case T_WORM:
- case T_CDROM:
- case T_SCANNER:
- case T_OPTICAL:
- case T_CHANGER:
- case T_COMM:
- case T_STORARRAY:
- case T_ENCLOSURE:
- case T_RBC:
- case T_OCRW:
- case T_OSD:
- case T_ADC:
- break;
- case T_NODEVICE:
- default:
+ if (type == T_NODEVICE)
return (0);
- }
-
- /*
- * Check vendor, product, and revision
- */
- cam_strvis(vendor, inq_data->vendor, sizeof(inq_data->vendor),
- sizeof(vendor));
- cam_strvis(product, inq_data->product, sizeof(inq_data->product),
- sizeof(product));
- cam_strvis(revision, inq_data->revision, sizeof(inq_data->revision),
- sizeof(revision));
- if (strlen(vendor) == 0 ||
- strlen(product) == 0 ||
- strlen(revision) == 0)
+ if (SID_QUAL(inq_data) == SID_QUAL_BAD_LU)
return (0);
-
return (1);
}
-
/**
* @brief completion function before returning to CAM
*
@@ -2039,6 +2030,7 @@
mtx_unlock(&sc->hs_lock);
}
+#ifdef notyet
/*
* callout_drain() will wait for the timer handler to finish
* if it is running. So we don't need any lock to synchronize
@@ -2049,33 +2041,109 @@
if (ccb->ccb_h.timeout != CAM_TIME_INFINITY) {
callout_drain(&reqp->callout);
}
-
+#endif
ccb->ccb_h.status &= ~CAM_SIM_QUEUED;
ccb->ccb_h.status &= ~CAM_STATUS_MASK;
if (vm_srb->scsi_status == SCSI_STATUS_OK) {
const struct scsi_generic *cmd;
-
- /*
- * Check whether the data for INQUIRY cmd is valid or
- * not. Windows 10 and Windows 2016 send all zero
- * inquiry data to VM even for unpopulated slots.
- */
cmd = (const struct scsi_generic *)
((ccb->ccb_h.flags & CAM_CDB_POINTER) ?
csio->cdb_io.cdb_ptr : csio->cdb_io.cdb_bytes);
- if (cmd->opcode == INQUIRY &&
- is_inquiry_valid(
- (const struct scsi_inquiry_data *)csio->data_ptr) == 0) {
- ccb->ccb_h.status |= CAM_DEV_NOT_THERE;
+ if (vm_srb->srb_status != SRB_STATUS_SUCCESS) {
+ /*
+ * If there are errors, for example, invalid LUN,
+ * host will inform VM through SRB status.
+ */
if (bootverbose) {
- mtx_lock(&sc->hs_lock);
- xpt_print(ccb->ccb_h.path,
- "storvsc uninstalled device\n");
- mtx_unlock(&sc->hs_lock);
+ if (vm_srb->srb_status == SRB_STATUS_INVALID_LUN) {
+ xpt_print(ccb->ccb_h.path,
+ "invalid LUN %d for op: %s\n",
+ vm_srb->lun,
+ scsi_op_desc(cmd->opcode, NULL));
+ } else {
+ xpt_print(ccb->ccb_h.path,
+ "Unknown SRB flag: %d for op: %s\n",
+ vm_srb->srb_status,
+ scsi_op_desc(cmd->opcode, NULL));
+ }
}
+
+ /*
+ * XXX For a selection timeout, all of the LUNs
+ * on the target will be gone. It works for SCSI
+ * disks, but does not work for IDE disks.
+ *
+ * For CAM_DEV_NOT_THERE, CAM will only get
+ * rid of the device(s) specified by the path.
+ */
+ if (storvsc_get_storage_type(sc->hs_dev->device) ==
+ DRIVER_STORVSC)
+ ccb->ccb_h.status |= CAM_SEL_TIMEOUT;
+ else
+ ccb->ccb_h.status |= CAM_DEV_NOT_THERE;
} else {
ccb->ccb_h.status |= CAM_REQ_CMP;
}
+
+ if (cmd->opcode == INQUIRY &&
+ vm_srb->srb_status == SRB_STATUS_SUCCESS) {
+ int resp_xfer_len, resp_buf_len, data_len;
+ struct scsi_inquiry_data *inq_data =
+ (struct scsi_inquiry_data *)csio->data_ptr;
+ /* Get the buffer length reported by host */
+ resp_xfer_len = vm_srb->transfer_len;
+ uint8_t *resp_buf = (uint8_t *)csio->data_ptr;
+
+ /* Get the available buffer length */
+ resp_buf_len = resp_xfer_len >= 5 ? resp_buf[4] + 5 : 0;
+ data_len = (resp_buf_len < resp_xfer_len) ?
+ resp_buf_len : resp_xfer_len;
+ if (bootverbose && data_len >= 5) {
+ xpt_print(ccb->ccb_h.path, "storvsc inquiry "
+ "(%d) [%x %x %x %x %x ... ]\n", data_len,
+ resp_buf[0], resp_buf[1], resp_buf[2],
+ resp_buf[3], resp_buf[4]);
+ }
+ /*
+ * XXX: Manually fix the wrong response returned from WS2012
+ */
+ if (!is_scsi_valid(inq_data) &&
+ (vmstor_proto_version == VMSTOR_PROTOCOL_VERSION_WIN8_1 ||
+ vmstor_proto_version == VMSTOR_PROTOCOL_VERSION_WIN8 ||
+ vmstor_proto_version == VMSTOR_PROTOCOL_VERSION_WIN7)) {
+ if (data_len >= 4 &&
+ (resp_buf[2] == 0 || resp_buf[3] == 0)) {
+ resp_buf[2] = 5; // verion=5 means SPC-3
+ resp_buf[3] = 2; // resp fmt must be 2
+ if (bootverbose)
+ xpt_print(ccb->ccb_h.path,
+ "fix version and resp fmt for 0x%x\n",
+ vmstor_proto_version);
+ }
+ } else if (data_len >= SHORT_INQUIRY_LENGTH) {
+ char vendor[16];
+
+ cam_strvis(vendor, inq_data->vendor,
+ sizeof(inq_data->vendor), sizeof(vendor));
+ /*
+ * XXX: Upgrade SPC2 to SPC3 if host is WIN8 or
+ * WIN2012 R2 in order to support UNMAP feature.
+ */
+ if (!strncmp(vendor, "Msft", 4) &&
+ SID_ANSI_REV(inq_data) == SCSI_REV_SPC2 &&
+ (vmstor_proto_version ==
+ VMSTOR_PROTOCOL_VERSION_WIN8_1 ||
+ vmstor_proto_version ==
+ VMSTOR_PROTOCOL_VERSION_WIN8)) {
+ inq_data->version = SCSI_REV_SPC3;
+ if (bootverbose) {
+ xpt_print(ccb->ccb_h.path,
+ "storvsc upgrades "
+ "SPC2 to SPC3\n");
+ }
+ }
+ }
+ }
} else {
mtx_lock(&sc->hs_lock);
xpt_print(ccb->ccb_h.path,
@@ -2143,3 +2211,51 @@
return (DRIVER_UNKNOWN);
}
+#define PCI_VENDOR_INTEL 0x8086
+#define PCI_PRODUCT_PIIX4 0x7111
+
+static void
+storvsc_ada_probe_veto(void *arg __unused, struct cam_path *path,
+ struct ata_params *ident_buf __unused, int *veto)
+{
+ /*
+ * Hyper-V should ignore ATA
+ */
+ if (path->device->protocol == PROTO_ATA) {
+ struct ccb_pathinq cpi;
+
+ bzero(&cpi, sizeof(cpi));
+ xpt_setup_ccb(&cpi.ccb_h, path, CAM_PRIORITY_NONE);
+ cpi.ccb_h.func_code = XPT_PATH_INQ;
+ xpt_action((union ccb *)&cpi);
+ if (cpi.ccb_h.status == CAM_REQ_CMP &&
+ cpi.hba_vendor == PCI_VENDOR_INTEL &&
+ cpi.hba_device == PCI_PRODUCT_PIIX4) {
+ (*veto)++;
+ xpt_print(path,
+ "Disable ATA for vendor: %x, device: %x\n",
+ cpi.hba_vendor, cpi.hba_device);
+ }
+ }
+}
+
+static void
+storvsc_sysinit(void *arg __unused)
+{
+ if (vm_guest == VM_GUEST_HV) {
+ storvsc_handler_tag = EVENTHANDLER_REGISTER(ada_probe_veto,
+ storvsc_ada_probe_veto, NULL, EVENTHANDLER_PRI_ANY);
+ }
+}
+SYSINIT(storvsc_sys_init, SI_SUB_DRIVERS, SI_ORDER_SECOND, storvsc_sysinit,
+ NULL);
+
+static void
+storvsc_sysuninit(void *arg __unused)
+{
+ if (storvsc_handler_tag != NULL) {
+ EVENTHANDLER_DEREGISTER(ada_probe_veto, storvsc_handler_tag);
+ }
+}
+SYSUNINIT(storvsc_sys_uninit, SI_SUB_DRIVERS, SI_ORDER_SECOND,
+ storvsc_sysuninit, NULL);
diff -ru --exclude-from freebsd-src-diff-exclude-names /var/tmp/freebsd-src/usr/src/sys/dev/hyperv/storvsc/hv_vstorage.h freebsd-10.3/usr/src/sys/dev/hyperv/storvsc/hv_vstorage.h
--- /var/tmp/freebsd-src/usr/src/sys/dev/hyperv/storvsc/hv_vstorage.h 2016-03-25 09:09:30.000000000 +0800
+++ freebsd-10.3/usr/src/sys/dev/hyperv/storvsc/hv_vstorage.h 2017-07-24 14:04:44.694126333 +0800
@@ -41,6 +41,11 @@
#define VMSTOR_PROTOCOL_VERSION(MAJOR_, MINOR_) ((((MAJOR_) & 0xff) << 8) | \
(((MINOR_) & 0xff) ))
+#define VMSTOR_PROTOCOL_VERSION_WIN6 VMSTOR_PROTOCOL_VERSION(2, 0)
+#define VMSTOR_PROTOCOL_VERSION_WIN7 VMSTOR_PROTOCOL_VERSION(4, 2)
+#define VMSTOR_PROTOCOL_VERSION_WIN8 VMSTOR_PROTOCOL_VERSION(5, 1)
+#define VMSTOR_PROTOCOL_VERSION_WIN8_1 VMSTOR_PROTOCOL_VERSION(6, 0)
+#define VMSTOR_PROTOCOL_VERSION_WIN10 VMSTOR_PROTOCOL_VERSION(6, 2)
/*
* Invalid version.
*/
@@ -244,9 +249,9 @@
/**
* SRB Status Masks (can be combined with above status codes)
*/
-#define SRB_STATUS_QUEUE_FROZEN 0x40
-#define SRB_STATUS_AUTOSENSE_VALID 0x80
-
+#define SRB_STATUS_QUEUE_FROZEN 0x40
+#define SRB_STATUS_AUTOSENSE_VALID 0x80
+#define SRB_STATUS_INVALID_LUN 0X20
/**
* Packet flags
diff -ru --exclude-from freebsd-src-diff-exclude-names /var/tmp/freebsd-src/usr/src/sys/dev/hyperv/utilities/hv_kvp.c freebsd-10.3/usr/src/sys/dev/hyperv/utilities/hv_kvp.c
--- /var/tmp/freebsd-src/usr/src/sys/dev/hyperv/utilities/hv_kvp.c 2016-03-25 09:09:30.000000000 +0800
+++ freebsd-10.3/usr/src/sys/dev/hyperv/utilities/hv_kvp.c 2017-07-24 14:04:44.699124587 +0800
@@ -311,28 +311,11 @@
{
int err_ip, err_subnet, err_gway, err_dns, err_adap;
int UNUSED_FLAG = 1;
- int guid_index;
struct hv_device *hv_dev; /* GUID Data Structure */
hn_softc_t *sc; /* hn softc structure */
char if_name[4];
- unsigned char guid_instance[40];
- char *guid_data = NULL;
char buf[39];
- struct guid_extract {
- char a1[2];
- char a2[2];
- char a3[2];
- char a4[2];
- char b1[2];
- char b2[2];
- char c1[2];
- char c2[2];
- char d[4];
- char e[12];
- };
-
- struct guid_extract *id;
device_t *devs;
int devcnt;
@@ -359,17 +342,7 @@
/* Trying to find GUID of Network Device */
hv_dev = sc->hn_dev_obj;
- for (guid_index = 0; guid_index < 16; guid_index++) {
- sprintf(&guid_instance[guid_index * 2], "%02x",
- hv_dev->device_id.data[guid_index]);
- }
-
- guid_data = (char *)guid_instance;
- id = (struct guid_extract *)guid_data;
- snprintf(buf, sizeof(buf), "{%.2s%.2s%.2s%.2s-%.2s%.2s-%.2s%.2s-%.4s-%s}",
- id->a4, id->a3, id->a2, id->a1,
- id->b2, id->b1, id->c2, id->c1, id->d, id->e);
- guid_data = NULL;
+ snprintf_hv_guid(buf, sizeof(buf), &hv_dev->device_id);
sprintf(if_name, "%s%d", "hn", device_get_unit(devs[devcnt]));
if (strncmp(buf, (char *)umsg->body.kvp_ip_val.adapter_id, 39) == 0) {
diff -ru --exclude-from freebsd-src-diff-exclude-names /var/tmp/freebsd-src/usr/src/sys/dev/hyperv/vmbus/hv_channel.c freebsd-10.3/usr/src/sys/dev/hyperv/vmbus/hv_channel.c
--- /var/tmp/freebsd-src/usr/src/sys/dev/hyperv/vmbus/hv_channel.c 2016-03-25 09:09:30.000000000 +0800
+++ freebsd-10.3/usr/src/sys/dev/hyperv/vmbus/hv_channel.c 2017-07-24 12:45:00.463452564 +0800
@@ -180,12 +180,12 @@
if (user_data_len)
memcpy(open_msg->user_data, user_data, user_data_len);
- mtx_lock_spin(&hv_vmbus_g_connection.channel_msg_lock);
+ mtx_lock(&hv_vmbus_g_connection.channel_msg_lock);
TAILQ_INSERT_TAIL(
&hv_vmbus_g_connection.channel_msg_anchor,
open_info,
msg_list_entry);
- mtx_unlock_spin(&hv_vmbus_g_connection.channel_msg_lock);
+ mtx_unlock(&hv_vmbus_g_connection.channel_msg_lock);
ret = hv_vmbus_post_message(
open_msg, sizeof(hv_vmbus_channel_open_channel));
@@ -212,12 +212,12 @@
}
cleanup:
- mtx_lock_spin(&hv_vmbus_g_connection.channel_msg_lock);
+ mtx_lock(&hv_vmbus_g_connection.channel_msg_lock);
TAILQ_REMOVE(
&hv_vmbus_g_connection.channel_msg_anchor,
open_info,
msg_list_entry);
- mtx_unlock_spin(&hv_vmbus_g_connection.channel_msg_lock);
+ mtx_unlock(&hv_vmbus_g_connection.channel_msg_lock);
sema_destroy(&open_info->wait_sema);
free(open_info, M_DEVBUF);
@@ -401,13 +401,13 @@
gpadl_msg->child_rel_id = channel->offer_msg.child_rel_id;
gpadl_msg->gpadl = next_gpadl_handle;
- mtx_lock_spin(&hv_vmbus_g_connection.channel_msg_lock);
+ mtx_lock(&hv_vmbus_g_connection.channel_msg_lock);
TAILQ_INSERT_TAIL(
&hv_vmbus_g_connection.channel_msg_anchor,
msg_info,
msg_list_entry);
- mtx_unlock_spin(&hv_vmbus_g_connection.channel_msg_lock);
+ mtx_unlock(&hv_vmbus_g_connection.channel_msg_lock);
ret = hv_vmbus_post_message(
gpadl_msg,
@@ -446,10 +446,10 @@
cleanup:
- mtx_lock_spin(&hv_vmbus_g_connection.channel_msg_lock);
+ mtx_lock(&hv_vmbus_g_connection.channel_msg_lock);
TAILQ_REMOVE(&hv_vmbus_g_connection.channel_msg_anchor,
msg_info, msg_list_entry);
- mtx_unlock_spin(&hv_vmbus_g_connection.channel_msg_lock);
+ mtx_unlock(&hv_vmbus_g_connection.channel_msg_lock);
sema_destroy(&msg_info->wait_sema);
free(msg_info, M_DEVBUF);
@@ -488,10 +488,10 @@
msg->child_rel_id = channel->offer_msg.child_rel_id;
msg->gpadl = gpadl_handle;
- mtx_lock_spin(&hv_vmbus_g_connection.channel_msg_lock);
+ mtx_lock(&hv_vmbus_g_connection.channel_msg_lock);
TAILQ_INSERT_TAIL(&hv_vmbus_g_connection.channel_msg_anchor,
info, msg_list_entry);
- mtx_unlock_spin(&hv_vmbus_g_connection.channel_msg_lock);
+ mtx_unlock(&hv_vmbus_g_connection.channel_msg_lock);
ret = hv_vmbus_post_message(msg,
sizeof(hv_vmbus_channel_gpadl_teardown));
@@ -504,10 +504,10 @@
/*
* Received a torndown response
*/
- mtx_lock_spin(&hv_vmbus_g_connection.channel_msg_lock);
+ mtx_lock(&hv_vmbus_g_connection.channel_msg_lock);
TAILQ_REMOVE(&hv_vmbus_g_connection.channel_msg_anchor,
info, msg_list_entry);
- mtx_unlock_spin(&hv_vmbus_g_connection.channel_msg_lock);
+ mtx_unlock(&hv_vmbus_g_connection.channel_msg_lock);
sema_destroy(&info->wait_sema);
free(info, M_DEVBUF);
diff -ru --exclude-from freebsd-src-diff-exclude-names /var/tmp/freebsd-src/usr/src/sys/dev/hyperv/vmbus/hv_channel_mgmt.c freebsd-10.3/usr/src/sys/dev/hyperv/vmbus/hv_channel_mgmt.c
--- /var/tmp/freebsd-src/usr/src/sys/dev/hyperv/vmbus/hv_channel_mgmt.c 2016-03-25 09:09:30.000000000 +0800
+++ freebsd-10.3/usr/src/sys/dev/hyperv/vmbus/hv_channel_mgmt.c 2017-07-24 12:45:00.468452326 +0800
@@ -567,7 +567,7 @@
/*
* Find the open msg, copy the result and signal/unblock the wait event
*/
- mtx_lock_spin(&hv_vmbus_g_connection.channel_msg_lock);
+ mtx_lock(&hv_vmbus_g_connection.channel_msg_lock);
TAILQ_FOREACH(msg_info, &hv_vmbus_g_connection.channel_msg_anchor,
msg_list_entry) {
@@ -585,7 +585,7 @@
}
}
}
- mtx_unlock_spin(&hv_vmbus_g_connection.channel_msg_lock);
+ mtx_unlock(&hv_vmbus_g_connection.channel_msg_lock);
}
@@ -609,7 +609,7 @@
/* Find the establish msg, copy the result and signal/unblock
* the wait event
*/
- mtx_lock_spin(&hv_vmbus_g_connection.channel_msg_lock);
+ mtx_lock(&hv_vmbus_g_connection.channel_msg_lock);
TAILQ_FOREACH(msg_info, &hv_vmbus_g_connection.channel_msg_anchor,
msg_list_entry) {
request_header = (hv_vmbus_channel_msg_header*) msg_info->msg;
@@ -628,7 +628,7 @@
}
}
}
- mtx_unlock_spin(&hv_vmbus_g_connection.channel_msg_lock);
+ mtx_unlock(&hv_vmbus_g_connection.channel_msg_lock);
}
/**
@@ -653,7 +653,7 @@
* wait event.
*/
- mtx_lock_spin(&hv_vmbus_g_connection.channel_msg_lock);
+ mtx_lock(&hv_vmbus_g_connection.channel_msg_lock);
TAILQ_FOREACH(msg_info, &hv_vmbus_g_connection.channel_msg_anchor,
msg_list_entry) {
@@ -673,7 +673,7 @@
}
}
}
- mtx_unlock_spin(&hv_vmbus_g_connection.channel_msg_lock);
+ mtx_unlock(&hv_vmbus_g_connection.channel_msg_lock);
}
/**
@@ -693,7 +693,7 @@
versionResponse = (hv_vmbus_channel_version_response*)hdr;
- mtx_lock_spin(&hv_vmbus_g_connection.channel_msg_lock);
+ mtx_lock(&hv_vmbus_g_connection.channel_msg_lock);
TAILQ_FOREACH(msg_info, &hv_vmbus_g_connection.channel_msg_anchor,
msg_list_entry) {
requestHeader = (hv_vmbus_channel_msg_header*) msg_info->msg;
@@ -707,7 +707,7 @@
sema_post(&msg_info->wait_sema);
}
}
- mtx_unlock_spin(&hv_vmbus_g_connection.channel_msg_lock);
+ mtx_unlock(&hv_vmbus_g_connection.channel_msg_lock);
}
diff -ru --exclude-from freebsd-src-diff-exclude-names /var/tmp/freebsd-src/usr/src/sys/dev/hyperv/vmbus/hv_connection.c freebsd-10.3/usr/src/sys/dev/hyperv/vmbus/hv_connection.c
--- /var/tmp/freebsd-src/usr/src/sys/dev/hyperv/vmbus/hv_connection.c 2016-03-25 09:09:30.000000000 +0800
+++ freebsd-10.3/usr/src/sys/dev/hyperv/vmbus/hv_connection.c 2017-07-24 12:45:00.472452882 +0800
@@ -101,26 +101,26 @@
* Add to list before we send the request since we may receive the
* response before returning from this routine
*/
- mtx_lock_spin(&hv_vmbus_g_connection.channel_msg_lock);
+ mtx_lock(&hv_vmbus_g_connection.channel_msg_lock);
TAILQ_INSERT_TAIL(
&hv_vmbus_g_connection.channel_msg_anchor,
msg_info,
msg_list_entry);
- mtx_unlock_spin(&hv_vmbus_g_connection.channel_msg_lock);
+ mtx_unlock(&hv_vmbus_g_connection.channel_msg_lock);
ret = hv_vmbus_post_message(
msg,
sizeof(hv_vmbus_channel_initiate_contact));
if (ret != 0) {
- mtx_lock_spin(&hv_vmbus_g_connection.channel_msg_lock);
+ mtx_lock(&hv_vmbus_g_connection.channel_msg_lock);
TAILQ_REMOVE(
&hv_vmbus_g_connection.channel_msg_anchor,
msg_info,
msg_list_entry);
- mtx_unlock_spin(&hv_vmbus_g_connection.channel_msg_lock);
+ mtx_unlock(&hv_vmbus_g_connection.channel_msg_lock);
return (ret);
}
@@ -129,12 +129,12 @@
*/
ret = sema_timedwait(&msg_info->wait_sema, 5 * hz); /* KYS 5 seconds */
- mtx_lock_spin(&hv_vmbus_g_connection.channel_msg_lock);
+ mtx_lock(&hv_vmbus_g_connection.channel_msg_lock);
TAILQ_REMOVE(
&hv_vmbus_g_connection.channel_msg_anchor,
msg_info,
msg_list_entry);
- mtx_unlock_spin(&hv_vmbus_g_connection.channel_msg_lock);
+ mtx_unlock(&hv_vmbus_g_connection.channel_msg_lock);
/**
* Check if successful
@@ -173,7 +173,7 @@
TAILQ_INIT(&hv_vmbus_g_connection.channel_msg_anchor);
mtx_init(&hv_vmbus_g_connection.channel_msg_lock, "vmbus channel msg",
- NULL, MTX_SPIN);
+ NULL, MTX_DEF);
TAILQ_INIT(&hv_vmbus_g_connection.channel_anchor);
mtx_init(&hv_vmbus_g_connection.channel_lock, "vmbus channel",
@@ -476,31 +476,35 @@
/**
* Send a msg on the vmbus's message connection
*/
-int hv_vmbus_post_message(void *buffer, size_t bufferLen) {
- int ret = 0;
+int hv_vmbus_post_message(void *buffer, size_t bufferLen)
+{
hv_vmbus_connection_id connId;
- unsigned retries = 0;
+ sbintime_t time = SBT_1MS;
+ int retries;
+ int ret;
- /* NetScaler delays from previous code were consolidated here */
- static int delayAmount[] = {100, 100, 100, 500, 500, 5000, 5000, 5000};
+ connId.as_uint32_t = 0;
+ connId.u.id = HV_VMBUS_MESSAGE_CONNECTION_ID;
- /* for(each entry in delayAmount) try to post message,
- * delay a little bit before retrying
+ /*
+ * We retry to cope with transient failures caused by host side's
+ * insufficient resources. 20 times should suffice in practice.
*/
- for (retries = 0;
- retries < sizeof(delayAmount)/sizeof(delayAmount[0]); retries++) {
- connId.as_uint32_t = 0;
- connId.u.id = HV_VMBUS_MESSAGE_CONNECTION_ID;
- ret = hv_vmbus_post_msg_via_msg_ipc(connId, 1, buffer, bufferLen);
- if (ret != HV_STATUS_INSUFFICIENT_BUFFERS)
- break;
- /* TODO: KYS We should use a blocking wait call */
- DELAY(delayAmount[retries]);
+ for (retries = 0; retries < 20; retries++) {
+ ret = hv_vmbus_post_msg_via_msg_ipc(connId, 1, buffer,
+ bufferLen);
+ if (ret == HV_STATUS_SUCCESS)
+ return (0);
+
+ pause_sbt("pstmsg", time, 0, C_HARDCLOCK);
+ if (time < SBT_1S * 2)
+ time *= 2;
}
- KASSERT(ret == 0, ("Error VMBUS: Message Post Failed\n"));
+ KASSERT(ret == HV_STATUS_SUCCESS,
+ ("Error VMBUS: Message Post Failed, ret=%d\n", ret));
- return (ret);
+ return (EAGAIN);
}
/**
diff -ru --exclude-from freebsd-src-diff-exclude-names /var/tmp/freebsd-src/usr/src/sys/dev/hyperv/vmbus/hv_hv.c freebsd-10.3/usr/src/sys/dev/hyperv/vmbus/hv_hv.c
--- /var/tmp/freebsd-src/usr/src/sys/dev/hyperv/vmbus/hv_hv.c 2016-03-25 09:09:30.000000000 +0800
+++ freebsd-10.3/usr/src/sys/dev/hyperv/vmbus/hv_hv.c 2017-07-24 14:04:44.714125164 +0800
@@ -33,6 +33,7 @@
__FBSDID("$FreeBSD: releng/10.3/sys/dev/hyperv/vmbus/hv_hv.c 295789 2016-02-19 02:03:14Z sephe $");
#include <sys/param.h>
+#include <sys/kernel.h>
#include <sys/malloc.h>
#include <sys/pcpu.h>
#include <sys/timetc.h>
@@ -50,6 +51,9 @@
static u_int hv_get_timecount(struct timecounter *tc);
+u_int hyperv_features;
+u_int hyperv_recommends;
+
/**
* Globals
*/
@@ -211,8 +215,6 @@
hv_vmbus_g_context.hypercall_page = virt_addr;
- tc_init(&hv_timecounter); /* register virtual timecount */
-
hv_et_init();
return (0);
@@ -427,3 +429,93 @@
wrmsr(HV_X64_MSR_SIEFP, siefp.as_uint64_t);
}
+static bool
+hyperv_identify(void)
+{
+ u_int regs[4];
+ unsigned int maxLeaf;
+ unsigned int op;
+
+ if (vm_guest != VM_GUEST_HV)
+ return (false);
+
+ op = HV_CPU_ID_FUNCTION_HV_VENDOR_AND_MAX_FUNCTION;
+ do_cpuid(op, regs);
+ maxLeaf = regs[0];
+ if (maxLeaf < HV_CPU_ID_FUNCTION_MS_HV_IMPLEMENTATION_LIMITS)
+ return (false);
+
+ op = HV_CPU_ID_FUNCTION_HV_INTERFACE;
+ do_cpuid(op, regs);
+ if (regs[0] != 0x31237648 /* HV#1 */)
+ return (false);
+
+ op = HV_CPU_ID_FUNCTION_MS_HV_FEATURES;
+ do_cpuid(op, regs);
+ if ((regs[0] & HV_FEATURE_MSR_HYPERCALL) == 0) {
+ /*
+ * Hyper-V w/o Hypercall is impossible; someone
+ * is faking Hyper-V.
+ */
+ return (false);
+ }
+ hyperv_features = regs[0];
+
+ op = HV_CPU_ID_FUNCTION_MS_HV_VERSION;
+ do_cpuid(op, regs);
+ printf("Hyper-V Version: %d.%d.%d [SP%d]\n",
+ regs[1] >> 16, regs[1] & 0xffff, regs[0], regs[2]);
+
+ printf(" Features: 0x%b\n", hyperv_features,
+ "\020"
+ "\001VPRUNTIME"
+ "\002TMREFCNT"
+ "\003SYNCIC"
+ "\004SYNCTM"
+ "\005APIC"
+ "\006HYERCALL"
+ "\007VPINDEX"
+ "\010RESET"
+ "\011STATS"
+ "\012REFTSC"
+ "\013IDLE"
+ "\014TMFREQ"
+ "\015DEBUG");
+
+ op = HV_CPU_ID_FUNCTION_MS_HV_ENLIGHTENMENT_INFORMATION;
+ do_cpuid(op, regs);
+ hyperv_recommends = regs[0];
+ if (bootverbose)
+ printf(" Recommends: %08x %08x\n", regs[0], regs[1]);
+
+ op = HV_CPU_ID_FUNCTION_MS_HV_IMPLEMENTATION_LIMITS;
+ do_cpuid(op, regs);
+ if (bootverbose) {
+ printf(" Limits: Vcpu:%d Lcpu:%d Int:%d\n",
+ regs[0], regs[1], regs[2]);
+ }
+
+ if (maxLeaf >= HV_CPU_ID_FUNCTION_MS_HV_HARDWARE_FEATURE) {
+ op = HV_CPU_ID_FUNCTION_MS_HV_HARDWARE_FEATURE;
+ do_cpuid(op, regs);
+ if (bootverbose) {
+ printf(" HW Features: %08x AMD: %08x\n",
+ regs[0], regs[3]);
+ }
+ }
+
+ return (true);
+}
+
+static void
+hyperv_init(void *dummy __unused)
+{
+ if (!hyperv_identify())
+ return;
+
+ if (hyperv_features & HV_FEATURE_MSR_TIME_REFCNT) {
+ /* Register virtual timecount */
+ tc_init(&hv_timecounter);
+ }
+}
+SYSINIT(hyperv_initialize, SI_SUB_HYPERVISOR, SI_ORDER_FIRST, hyperv_init, NULL);
diff -ru --exclude-from freebsd-src-diff-exclude-names /var/tmp/freebsd-src/usr/src/sys/dev/hyperv/vmbus/hv_vmbus_drv_freebsd.c freebsd-10.3/usr/src/sys/dev/hyperv/vmbus/hv_vmbus_drv_freebsd.c
--- /var/tmp/freebsd-src/usr/src/sys/dev/hyperv/vmbus/hv_vmbus_drv_freebsd.c 2016-03-25 09:09:30.000000000 +0800
+++ freebsd-10.3/usr/src/sys/dev/hyperv/vmbus/hv_vmbus_drv_freebsd.c 2017-07-24 14:04:44.732122581 +0800
@@ -59,6 +59,7 @@
#include <sys/pcpu.h>
#include <machine/apicvar.h>
+#include <dev/hyperv/include/hyperv.h>
#include "hv_vmbus_priv.h"
#include <contrib/dev/acpica/include/acpi.h>
@@ -298,6 +299,23 @@
return (ENOENT);
}
+static int
+vmbus_child_pnpinfo_str(device_t dev, device_t child, char *buf, size_t buflen)
+{
+ char guidbuf[40];
+ struct hv_device *dev_ctx = device_get_ivars(child);
+
+ strlcat(buf, "classid=", buflen);
+ snprintf_hv_guid(guidbuf, sizeof(guidbuf), &dev_ctx->class_id);
+ strlcat(buf, guidbuf, buflen);
+
+ strlcat(buf, " deviceid=", buflen);
+ snprintf_hv_guid(guidbuf, sizeof(guidbuf), &dev_ctx->device_id);
+ strlcat(buf, guidbuf, buflen);
+
+ return (0);
+}
+
struct hv_device*
hv_vmbus_child_device_create(
hv_guid type,
@@ -324,15 +342,17 @@
return (child_dev);
}
-static void
-print_dev_guid(struct hv_device *dev)
+int
+snprintf_hv_guid(char *buf, size_t sz, const hv_guid *guid)
{
- int i;
- unsigned char guid_name[100];
- for (i = 0; i < 32; i += 2)
- sprintf(&guid_name[i], "%02x", dev->class_id.data[i / 2]);
- if(bootverbose)
- printf("VMBUS: Class ID: %s\n", guid_name);
+ int cnt;
+ const unsigned char *d = guid->data;
+
+ cnt = snprintf(buf, sz,
+ "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
+ d[3], d[2], d[1], d[0], d[5], d[4], d[7], d[6],
+ d[8], d[9], d[10], d[11], d[12], d[13], d[14], d[15]);
+ return (cnt);
}
int
@@ -341,8 +361,11 @@
device_t child;
int ret = 0;
- print_dev_guid(child_dev);
-
+ if (bootverbose) {
+ char name[40];
+ snprintf_hv_guid(name, sizeof(name), &child_dev->class_id);
+ printf("VMBUS: Class ID: %s\n", name);
+ }
child = device_add_child(vmbus_devp, NULL, -1);
child_dev->device = child;
@@ -747,6 +770,7 @@
DEVMETHOD(bus_print_child, bus_generic_print_child),
DEVMETHOD(bus_read_ivar, vmbus_read_ivar),
DEVMETHOD(bus_write_ivar, vmbus_write_ivar),
+ DEVMETHOD(bus_child_pnpinfo_str, vmbus_child_pnpinfo_str),
{ 0, 0 } };
diff -ru --exclude-from freebsd-src-diff-exclude-names /var/tmp/freebsd-src/usr/src/sys/dev/hyperv/vmbus/hv_vmbus_priv.h freebsd-10.3/usr/src/sys/dev/hyperv/vmbus/hv_vmbus_priv.h
--- /var/tmp/freebsd-src/usr/src/sys/dev/hyperv/vmbus/hv_vmbus_priv.h 2016-03-25 09:09:30.000000000 +0800
+++ freebsd-10.3/usr/src/sys/dev/hyperv/vmbus/hv_vmbus_priv.h 2017-07-24 12:45:00.476452893 +0800
@@ -70,6 +70,7 @@
* You did not supply enough message buffers to send a message.
*/
+#define HV_STATUS_SUCCESS ((uint16_t)0)
#define HV_STATUS_INSUFFICIENT_BUFFERS ((uint16_t)0x0013)
typedef void (*hv_vmbus_channel_callback)(void *context);
@@ -471,10 +472,17 @@
HV_CPU_ID_FUNCTION_MS_HV_VERSION = 0x40000002,
HV_CPU_ID_FUNCTION_MS_HV_FEATURES = 0x40000003,
HV_CPU_ID_FUNCTION_MS_HV_ENLIGHTENMENT_INFORMATION = 0x40000004,
- HV_CPU_ID_FUNCTION_MS_HV_IMPLEMENTATION_LIMITS = 0x40000005
-
+ HV_CPU_ID_FUNCTION_MS_HV_IMPLEMENTATION_LIMITS = 0x40000005,
+ HV_CPU_ID_FUNCTION_MS_HV_HARDWARE_FEATURE = 0x40000006
} hv_vmbus_cpuid_function;
+#define HV_FEATURE_MSR_TIME_REFCNT (1 << 1)
+#define HV_FEATURE_MSR_SYNCIC (1 << 2)
+#define HV_FEATURE_MSR_STIMER (1 << 3)
+#define HV_FEATURE_MSR_APIC (1 << 4)
+#define HV_FEATURE_MSR_HYPERCALL (1 << 5)
+#define HV_FEATURE_MSR_GUEST_IDLE (1 << 10)
+
/*
* Define the format of the SIMP register
*/
@@ -628,6 +636,9 @@
extern hv_vmbus_context hv_vmbus_g_context;
extern hv_vmbus_connection hv_vmbus_g_connection;
+extern u_int hyperv_features;
+extern u_int hyperv_recommends;
+
typedef void (*vmbus_msg_handler)(hv_vmbus_channel_msg_header *msg);
typedef struct hv_vmbus_channel_msg_table_entry {
diff -ru --exclude-from freebsd-src-diff-exclude-names /var/tmp/freebsd-src/usr/src/sys/dev/kbd/kbd.c freebsd-10.3/usr/src/sys/dev/kbd/kbd.c
--- /var/tmp/freebsd-src/usr/src/sys/dev/kbd/kbd.c 2016-03-25 09:09:39.000000000 +0800
+++ freebsd-10.3/usr/src/sys/dev/kbd/kbd.c 2017-07-24 12:45:00.481453439 +0800
@@ -996,7 +996,7 @@
splx(s);
return (error);
}
- kbd->kb_fkeytab[fkeyp->keynum].len = imin(fkeyp->flen, MAXFK);
+ kbd->kb_fkeytab[fkeyp->keynum].len = min(fkeyp->flen, MAXFK);
bcopy(fkeyp->keydef, kbd->kb_fkeytab[fkeyp->keynum].str,
kbd->kb_fkeytab[fkeyp->keynum].len);
break;
Only in freebsd-10.3/usr/src/sys/dev: one
diff -ru --exclude-from freebsd-src-diff-exclude-names /var/tmp/freebsd-src/usr/src/sys/dev/xen/blkfront/blkfront.c freebsd-10.3/usr/src/sys/dev/xen/blkfront/blkfront.c
--- /var/tmp/freebsd-src/usr/src/sys/dev/xen/blkfront/blkfront.c 2016-03-25 09:09:33.000000000 +0800
+++ freebsd-10.3/usr/src/sys/dev/xen/blkfront/blkfront.c 2017-07-24 14:04:44.741123044 +0800
@@ -1503,6 +1503,11 @@
{
struct xbd_softc *sc = device_get_softc(dev);
+ if (xen_suspend_cancelled) {
+ sc->xbd_state = XBD_STATE_CONNECTED;
+ return (0);
+ }
+
DPRINTK("xbd_resume: %s\n", xenbus_get_node(dev));
xbd_free(sc);
diff -ru --exclude-from freebsd-src-diff-exclude-names /var/tmp/freebsd-src/usr/src/sys/dev/xen/control/control.c freebsd-10.3/usr/src/sys/dev/xen/control/control.c
--- /var/tmp/freebsd-src/usr/src/sys/dev/xen/control/control.c 2016-03-25 09:09:33.000000000 +0800
+++ freebsd-10.3/usr/src/sys/dev/xen/control/control.c 2017-07-24 14:04:44.756124074 +0800
@@ -151,6 +151,7 @@
#include <machine/xen/xenvar.h>
#include <machine/xen/xenfunc.h>
+bool xen_suspend_cancelled;
/*--------------------------- Forward Declarations --------------------------*/
/** Function signature for shutdown event handlers. */
typedef void (xctrl_shutdown_handler_t)(void);
@@ -341,8 +342,11 @@
#ifdef SMP
cpuset_t cpu_suspend_map;
#endif
- int suspend_cancelled;
+ EVENTHANDLER_INVOKE(power_suspend_early);
+ xs_lock();
+ stop_all_proc();
+ xs_unlock();
EVENTHANDLER_INVOKE(power_suspend);
if (smp_started) {
@@ -392,16 +396,20 @@
intr_suspend();
xen_hvm_suspend();
- suspend_cancelled = HYPERVISOR_suspend(0);
+ xen_suspend_cancelled = !!HYPERVISOR_suspend(0);
- xen_hvm_resume(suspend_cancelled != 0);
- intr_resume(suspend_cancelled != 0);
+ if (!xen_suspend_cancelled) {
+ xen_hvm_resume(false);
+ }
+ intr_resume(xen_suspend_cancelled != 0);
enable_intr();
/*
* Reset grant table info.
*/
- gnttab_resume();
+ if (!xen_suspend_cancelled) {
+ gnttab_resume();
+ }
#ifdef SMP
/* Send an IPI_BITMAP in case there are pending bitmap IPIs. */
@@ -429,6 +437,8 @@
thread_unlock(curthread);
}
+ resume_all_proc();
+
EVENTHANDLER_INVOKE(power_resume);
if (bootverbose)
diff -ru --exclude-from freebsd-src-diff-exclude-names /var/tmp/freebsd-src/usr/src/sys/dev/xen/netfront/netfront.c freebsd-10.3/usr/src/sys/dev/xen/netfront/netfront.c
--- /var/tmp/freebsd-src/usr/src/sys/dev/xen/netfront/netfront.c 2016-03-25 09:09:33.000000000 +0800
+++ freebsd-10.3/usr/src/sys/dev/xen/netfront/netfront.c 2017-07-24 14:04:44.777122892 +0800
@@ -509,6 +509,15 @@
{
struct netfront_info *info = device_get_softc(dev);
+ if (xen_suspend_cancelled) {
+ XN_RX_LOCK(info);
+ XN_TX_LOCK(info);
+ netfront_carrier_on(info);
+ XN_TX_UNLOCK(info);
+ XN_RX_UNLOCK(info);
+ return (0);
+ }
+
info->xn_resume = true;
netif_disconnect_backend(info);
return (0);
@@ -796,6 +805,45 @@
}
static void
+netif_release_rx_bufs_copy(struct netfront_info *np)
+{
+ struct mbuf *m;
+ grant_ref_t ref;
+ unsigned int i, busy, inuse;
+
+ XN_RX_LOCK(np);
+
+ for (busy = inuse = i = 0; i < NET_RX_RING_SIZE; i++) {
+ ref = np->grant_rx_ref[i];
+
+ if (ref == GRANT_REF_INVALID)
+ continue;
+
+ inuse++;
+
+ m = np->rx_mbufs[i];
+
+ if (!gnttab_end_foreign_access_ref(ref)) {
+ busy++;
+ continue;
+ }
+
+ gnttab_release_grant_reference(&np->gref_rx_head, ref);
+ np->grant_rx_ref[i] = GRANT_REF_INVALID;
+ add_id_to_freelist(np->rx_mbufs, i);
+
+ m_freem(m);
+ }
+
+ if (busy != 0)
+ device_printf(np->xbdev,
+ "Unable to release %u of %u in use grant references out of %zu total.\n",
+ busy, inuse, NET_RX_RING_SIZE);
+
+ XN_RX_UNLOCK(np);
+}
+
+static void
network_alloc_rx_buffers(struct netfront_info *sc)
{
int otherend_id = xenbus_get_otherend_id(sc->xbdev);
@@ -2190,6 +2238,12 @@
info->xn_ifp = NULL;
}
ifmedia_removeall(&info->sc_media);
+ netif_release_tx_bufs(info);
+ if (info->copying_receiver)
+ netif_release_rx_bufs_copy(info);
+
+ gnttab_free_grant_references(info->gref_tx_head);
+ gnttab_free_grant_references(info->gref_rx_head);
}
static void
diff -ru --exclude-from freebsd-src-diff-exclude-names /var/tmp/freebsd-src/usr/src/sys/kern/init_main.c freebsd-10.3/usr/src/sys/kern/init_main.c
--- /var/tmp/freebsd-src/usr/src/sys/kern/init_main.c 2016-03-25 09:09:26.000000000 +0800
+++ freebsd-10.3/usr/src/sys/kern/init_main.c 2018-11-05 19:30:33.703793203 +0800
@@ -833,7 +833,7 @@
newcred = crget();
sx_xlock(&proctree_lock);
PROC_LOCK(initproc);
- initproc->p_flag |= P_SYSTEM | P_INMEM;
+ initproc->p_flag |= P_INMEM;
initproc->p_treeflag |= P_TREE_REAPER;
LIST_INSERT_HEAD(&initproc->p_reaplist, &proc0, p_reapsibling);
oldcred = initproc->p_ucred;
diff -ru --exclude-from freebsd-src-diff-exclude-names /var/tmp/freebsd-src/usr/src/sys/kern/uipc_syscalls.c freebsd-10.3/usr/src/sys/kern/uipc_syscalls.c
--- /var/tmp/freebsd-src/usr/src/sys/kern/uipc_syscalls.c 2016-03-25 09:09:26.000000000 +0800
+++ freebsd-10.3/usr/src/sys/kern/uipc_syscalls.c 2017-07-24 12:45:00.498452898 +0800
@@ -1787,6 +1787,9 @@
struct mbuf *m;
int error;
+ if (buflen < 0)
+ return (EINVAL);
+
if (buflen > MLEN) {
#ifdef COMPAT_OLDSOCK
if (type == MT_SONAME && buflen <= 112)
diff -ru --exclude-from freebsd-src-diff-exclude-names /var/tmp/freebsd-src/usr/src/sys/kern/vfs_subr.c freebsd-10.3/usr/src/sys/kern/vfs_subr.c
--- /var/tmp/freebsd-src/usr/src/sys/kern/vfs_subr.c 2016-03-25 09:09:26.000000000 +0800
+++ freebsd-10.3/usr/src/sys/kern/vfs_subr.c 2017-07-24 12:45:00.503452356 +0800
@@ -2934,7 +2934,13 @@
TAILQ_EMPTY(&vp->v_bufobj.bo_clean.bv_hd) &&
vp->v_bufobj.bo_clean.bv_cnt == 0,
("vp %p bufobj not invalidated", vp));
- vp->v_bufobj.bo_flag |= BO_DEAD;
+
+ /*
+ * For VMIO bufobj, BO_DEAD is set in vm_object_terminate()
+ * after the object's page queue is flushed.
+ */
+ if (vp->v_bufobj.bo_object == NULL)
+ vp->v_bufobj.bo_flag |= BO_DEAD;
BO_UNLOCK(&vp->v_bufobj);
/*
diff -ru --exclude-from freebsd-src-diff-exclude-names /var/tmp/freebsd-src/usr/src/sys/kern/vfs_syscalls.c freebsd-10.3/usr/src/sys/kern/vfs_syscalls.c
--- /var/tmp/freebsd-src/usr/src/sys/kern/vfs_syscalls.c 2016-03-25 09:09:26.000000000 +0800
+++ freebsd-10.3/usr/src/sys/kern/vfs_syscalls.c 2017-07-24 12:45:00.508455977 +0800
@@ -2197,6 +2197,7 @@
struct ostat *ost;
{
+ bzero(ost, sizeof(*ost));
ost->st_dev = st->st_dev;
ost->st_ino = st->st_ino;
ost->st_mode = st->st_mode;
diff -ru --exclude-from freebsd-src-diff-exclude-names /var/tmp/freebsd-src/usr/src/sys/sys/eventhandler.h freebsd-10.3/usr/src/sys/sys/eventhandler.h
--- /var/tmp/freebsd-src/usr/src/sys/sys/eventhandler.h 2016-03-25 09:09:26.000000000 +0800
+++ freebsd-10.3/usr/src/sys/sys/eventhandler.h 2017-07-24 14:04:44.806122993 +0800
@@ -283,4 +283,11 @@
EVENTHANDLER_DECLARE(register_framebuffer, register_framebuffer_fn);
EVENTHANDLER_DECLARE(unregister_framebuffer, unregister_framebuffer_fn);
+/* veto ada probing */
+struct cam_path;
+struct ata_params;
+typedef void (*ada_probe_veto_fn)(void *, struct cam_path *,
+ struct ata_params *, int *);
+EVENTHANDLER_DECLARE(ada_probe_veto, ada_probe_veto_fn);
+
#endif /* SYS_EVENTHANDLER_H */
diff -ru --exclude-from freebsd-src-diff-exclude-names /var/tmp/freebsd-src/usr/src/sys/vm/vm_fault.c freebsd-10.3/usr/src/sys/vm/vm_fault.c
--- /var/tmp/freebsd-src/usr/src/sys/vm/vm_fault.c 2016-03-25 09:09:47.000000000 +0800
+++ freebsd-10.3/usr/src/sys/vm/vm_fault.c 2017-07-24 12:45:00.512452069 +0800
@@ -286,7 +286,7 @@
vm_prot_t prot;
long ahead, behind;
int alloc_req, era, faultcount, nera, reqpage, result;
- boolean_t growstack, is_first_object_locked, wired;
+ boolean_t dead, growstack, is_first_object_locked, wired;
int map_generation;
vm_object_t next_object;
vm_page_t marray[VM_FAULT_READ_MAX];
@@ -423,11 +423,18 @@
fs.pindex = fs.first_pindex;
while (TRUE) {
/*
- * If the object is dead, we stop here
+ * If the object is marked for imminent termination,
+ * we retry here, since the collapse pass has raced
+ * with us. Otherwise, if we see terminally dead
+ * object, return fail.
*/
- if (fs.object->flags & OBJ_DEAD) {
+ if ((fs.object->flags & OBJ_DEAD) != 0) {
+ dead = fs.object->type == OBJT_DEAD;
unlock_and_deallocate(&fs);
- return (KERN_PROTECTION_FAILURE);
+ if (dead)
+ return (KERN_PROTECTION_FAILURE);
+ pause("vmf_de", 1);
+ goto RetryFault;
}
/*
diff -ru --exclude-from freebsd-src-diff-exclude-names /var/tmp/freebsd-src/usr/src/sys/vm/vm_meter.c freebsd-10.3/usr/src/sys/vm/vm_meter.c
--- /var/tmp/freebsd-src/usr/src/sys/vm/vm_meter.c 2016-03-25 09:09:47.000000000 +0800
+++ freebsd-10.3/usr/src/sys/vm/vm_meter.c 2017-07-24 12:45:00.517452330 +0800
@@ -93,29 +93,31 @@
CTLFLAG_MPSAFE, NULL, 0, sysctl_vm_loadavg, "S,loadavg",
"Machine loadaverage history");
+/*
+ * This function aims to determine if the object is mapped,
+ * specifically, if it is referenced by a vm_map_entry. Because
+ * objects occasionally acquire transient references that do not
+ * represent a mapping, the method used here is inexact. However, it
+ * has very low overhead and is good enough for the advisory
+ * vm.vmtotal sysctl.
+ */
+static bool
+is_object_active(vm_object_t obj)
+{
+
+ return (obj->ref_count > obj->shadow_count);
+}
+
static int
vmtotal(SYSCTL_HANDLER_ARGS)
{
- struct proc *p;
struct vmtotal total;
- vm_map_entry_t entry;
vm_object_t object;
- vm_map_t map;
- int paging;
+ struct proc *p;
struct thread *td;
- struct vmspace *vm;
bzero(&total, sizeof(total));
- /*
- * Mark all objects as inactive.
- */
- mtx_lock(&vm_object_list_mtx);
- TAILQ_FOREACH(object, &vm_object_list, object_list) {
- VM_OBJECT_WLOCK(object);
- vm_object_clear_flag(object, OBJ_ACTIVE);
- VM_OBJECT_WUNLOCK(object);
- }
- mtx_unlock(&vm_object_list_mtx);
+
/*
* Calculate process statistics.
*/
@@ -136,11 +138,15 @@
case TDS_INHIBITED:
if (TD_IS_SWAPPED(td))
total.t_sw++;
- else if (TD_IS_SLEEPING(td) &&
- td->td_priority <= PZERO)
- total.t_dw++;
- else
- total.t_sl++;
+ else if (TD_IS_SLEEPING(td)) {
+ if (td->td_priority <= PZERO)
+ total.t_dw++;
+ else
+ total.t_sl++;
+ if (td->td_wchan ==
+ &cnt.v_free_count)
+ total.t_pw++;
+ }
break;
case TDS_CAN_RUN:
@@ -158,29 +164,6 @@
}
}
PROC_UNLOCK(p);
- /*
- * Note active objects.
- */
- paging = 0;
- vm = vmspace_acquire_ref(p);
- if (vm == NULL)
- continue;
- map = &vm->vm_map;
- vm_map_lock_read(map);
- for (entry = map->header.next;
- entry != &map->header; entry = entry->next) {
- if ((entry->eflags & MAP_ENTRY_IS_SUB_MAP) ||
- (object = entry->object.vm_object) == NULL)
- continue;
- VM_OBJECT_WLOCK(object);
- vm_object_set_flag(object, OBJ_ACTIVE);
- paging |= object->paging_in_progress;
- VM_OBJECT_WUNLOCK(object);
- }
- vm_map_unlock_read(map);
- vmspace_free(vm);
- if (paging)
- total.t_pw++;
}
sx_sunlock(&allproc_lock);
/*
@@ -206,9 +189,18 @@
*/
continue;
}
+ if (object->ref_count == 1 &&
+ (object->flags & OBJ_NOSPLIT) != 0) {
+ /*
+ * Also skip otherwise unreferenced swap
+ * objects backing tmpfs vnodes, and POSIX or
+ * SysV shared memory.
+ */
+ continue;
+ }
total.t_vm += object->size;
total.t_rm += object->resident_page_count;
- if (object->flags & OBJ_ACTIVE) {
+ if (is_object_active(object)) {
total.t_avm += object->size;
total.t_arm += object->resident_page_count;
}
@@ -216,7 +208,7 @@
/* shared object */
total.t_vmshr += object->size;
total.t_rmshr += object->resident_page_count;
- if (object->flags & OBJ_ACTIVE) {
+ if (is_object_active(object)) {
total.t_avmshr += object->size;
total.t_armshr += object->resident_page_count;
}
diff -ru --exclude-from freebsd-src-diff-exclude-names /var/tmp/freebsd-src/usr/src/sys/vm/vm_object.c freebsd-10.3/usr/src/sys/vm/vm_object.c
--- /var/tmp/freebsd-src/usr/src/sys/vm/vm_object.c 2016-03-25 09:09:47.000000000 +0800
+++ freebsd-10.3/usr/src/sys/vm/vm_object.c 2017-07-24 12:45:00.522453379 +0800
@@ -737,6 +737,10 @@
vinvalbuf(vp, V_SAVE, 0, 0);
+ BO_LOCK(&vp->v_bufobj);
+ vp->v_bufobj.bo_flag |= BO_DEAD;
+ BO_UNLOCK(&vp->v_bufobj);
+
VM_OBJECT_WLOCK(object);
}
@@ -1722,6 +1726,9 @@
* case.
*/
if (backing_object->ref_count == 1) {
+ vm_object_pip_add(object, 1);
+ vm_object_pip_add(backing_object, 1);
+
/*
* If there is exactly one reference to the backing
* object, we can collapse it into the parent.
@@ -1793,11 +1800,13 @@
KASSERT(backing_object->ref_count == 1, (
"backing_object %p was somehow re-referenced during collapse!",
backing_object));
+ vm_object_pip_wakeup(backing_object);
backing_object->type = OBJT_DEAD;
backing_object->ref_count = 0;
VM_OBJECT_WUNLOCK(backing_object);
vm_object_destroy(backing_object);
+ vm_object_pip_wakeup(object);
object_collapses++;
} else {
vm_object_t new_backing_object;
@@ -2130,6 +2139,7 @@
*/
if (!reserved && !swap_reserve_by_cred(ptoa(next_size),
prev_object->cred)) {
+ VM_OBJECT_WUNLOCK(prev_object);
return (FALSE);
}
prev_object->charge += ptoa(next_size);
diff -ru --exclude-from freebsd-src-diff-exclude-names /var/tmp/freebsd-src/usr/src/sys/vm/vm_object.h freebsd-10.3/usr/src/sys/vm/vm_object.h
--- /var/tmp/freebsd-src/usr/src/sys/vm/vm_object.h 2016-03-25 09:09:47.000000000 +0800
+++ freebsd-10.3/usr/src/sys/vm/vm_object.h 2017-07-24 12:45:00.526452693 +0800
@@ -181,7 +181,6 @@
*/
#define OBJ_FICTITIOUS 0x0001 /* (c) contains fictitious pages */
#define OBJ_UNMANAGED 0x0002 /* (c) contains unmanaged pages */
-#define OBJ_ACTIVE 0x0004 /* active objects */
#define OBJ_DEAD 0x0008 /* dead objects (during rundown) */
#define OBJ_NOSPLIT 0x0010 /* dont split this object */
#define OBJ_PIPWNT 0x0040 /* paging in progress wanted */
diff -ru --exclude-from freebsd-src-diff-exclude-names /var/tmp/freebsd-src/usr/src/sys/x86/x86/intr_machdep.c freebsd-10.3/usr/src/sys/x86/x86/intr_machdep.c
--- /var/tmp/freebsd-src/usr/src/sys/x86/x86/intr_machdep.c 2016-03-25 09:09:43.000000000 +0800
+++ freebsd-10.3/usr/src/sys/x86/x86/intr_machdep.c 2017-07-24 14:04:44.833122606 +0800
@@ -535,6 +535,9 @@
if (mp_ncpus == 1)
return;
+ /* Does not work properly on Hyper-V. */
+ if (vm_guest == VM_GUEST_HV)
+ return;
/* Round-robin assign a CPU to each enabled source. */
mtx_lock(&intr_table_lock);
assign_cpu = 1;
diff -ru --exclude-from freebsd-src-diff-exclude-names /var/tmp/freebsd-src/usr/src/sys/x86/x86/local_apic.c freebsd-10.3/usr/src/sys/x86/x86/local_apic.c
--- /var/tmp/freebsd-src/usr/src/sys/x86/x86/local_apic.c 2016-03-25 09:09:43.000000000 +0800
+++ freebsd-10.3/usr/src/sys/x86/x86/local_apic.c 2017-07-24 12:45:00.531452028 +0800
@@ -56,6 +56,7 @@
#include <vm/pmap.h>
#include <x86/apicreg.h>
+#include <machine/clock.h>
#include <machine/cputypes.h>
#include <machine/frame.h>
#include <machine/intr_machdep.h>
@@ -158,6 +159,9 @@
vm_paddr_t lapic_paddr;
static u_long lapic_timer_divisor;
static struct eventtimer lapic_et;
+#ifdef SMP
+static uint64_t lapic_ipi_wait_mult;
+#endif
static void lapic_enable(void);
static void lapic_resume(struct pic *pic, bool suspend_cancelled);
@@ -221,6 +225,9 @@
void
lapic_init(vm_paddr_t addr)
{
+#ifdef SMP
+ uint64_t r, r1, r2, rx;
+#endif
u_int regs[4];
int i, arat;
@@ -275,6 +282,38 @@
lapic_et.et_priv = NULL;
et_register(&lapic_et);
}
+
+#ifdef SMP
+#define LOOPS 1000000
+ /*
+ * Calibrate the busy loop waiting for IPI ack in xAPIC mode.
+ * lapic_ipi_wait_mult contains the number of iterations which
+ * approximately delay execution for 1 microsecond (the
+ * argument to native_lapic_ipi_wait() is in microseconds).
+ *
+ * We assume that TSC is present and already measured.
+ * Possible TSC frequency jumps are irrelevant to the
+ * calibration loop below, the CPU clock management code is
+ * not yet started, and we do not enter sleep states.
+ */
+ KASSERT((cpu_feature & CPUID_TSC) != 0 && tsc_freq != 0,
+ ("TSC not initialized"));
+ r = rdtsc();
+ for (rx = 0; rx < LOOPS; rx++) {
+ (void)lapic->icr_lo;
+ ia32_pause();
+ }
+ r = rdtsc() - r;
+ r1 = tsc_freq * LOOPS;
+ r2 = r * 1000000;
+ lapic_ipi_wait_mult = r1 >= r2 ? r1 / r2 : 1;
+ if (bootverbose) {
+ printf("LAPIC: ipi_wait() us multiplier %ju (r %ju tsc %ju)\n",
+ (uintmax_t)lapic_ipi_wait_mult, (uintmax_t)r,
+ (uintmax_t)tsc_freq);
+ }
+#undef LOOPS
+#endif /* SMP */
}
/*
@@ -1381,25 +1420,20 @@
* private to the MD code. The public interface for the rest of the
* kernel is defined in mp_machdep.c.
*/
+
+/*
+ * Wait delay microseconds for IPI to be sent. If delay is -1, we
+ * wait forever.
+ */
int
lapic_ipi_wait(int delay)
{
- int x;
-
- /*
- * Wait delay microseconds for IPI to be sent. If delay is
- * -1, we wait forever.
- */
- if (delay == -1) {
- while ((lapic->icr_lo & APIC_DELSTAT_MASK) != APIC_DELSTAT_IDLE)
- ia32_pause();
- return (1);
- }
+ uint64_t rx;
- for (x = 0; x < delay; x += 5) {
+ for (rx = 0; delay == -1 || rx < lapic_ipi_wait_mult * delay; rx++) {
if ((lapic->icr_lo & APIC_DELSTAT_MASK) == APIC_DELSTAT_IDLE)
return (1);
- DELAY(5);
+ ia32_pause();
}
return (0);
}
diff -ru --exclude-from freebsd-src-diff-exclude-names /var/tmp/freebsd-src/usr/src/sys/xen/xen-os.h freebsd-10.3/usr/src/sys/xen/xen-os.h
--- /var/tmp/freebsd-src/usr/src/sys/xen/xen-os.h 2016-03-25 09:09:47.000000000 +0800
+++ freebsd-10.3/usr/src/sys/xen/xen-os.h 2017-07-24 14:04:44.865123013 +0800
@@ -57,6 +57,8 @@
extern int xen_disable_pv_nics;
#endif
+extern bool xen_suspend_cancelled;
+
enum xen_domain_type {
XEN_NATIVE, /* running on bare hardware */
XEN_PV_DOMAIN, /* running in a PV domain */
diff -ru --exclude-from freebsd-src-diff-exclude-names /var/tmp/freebsd-src/usr/src/sys/xen/xenbus/xenbusb.c freebsd-10.3/usr/src/sys/xen/xenbus/xenbusb.c
--- /var/tmp/freebsd-src/usr/src/sys/xen/xenbus/xenbusb.c 2016-03-25 09:09:47.000000000 +0800
+++ freebsd-10.3/usr/src/sys/xen/xenbus/xenbusb.c 2017-07-24 14:04:44.870124886 +0800
@@ -791,6 +791,11 @@
if (device_get_state(kids[i]) == DS_NOTPRESENT)
continue;
+ if (xen_suspend_cancelled) {
+ DEVICE_RESUME(kids[i]);
+ continue;
+ }
+
ivars = device_get_ivars(kids[i]);
xs_unregister_watch(&ivars->xd_otherend_watch);
diff -ru --exclude-from freebsd-src-diff-exclude-names /var/tmp/freebsd-src/usr/src/sys/xen/xenstore/xenstore.c freebsd-10.3/usr/src/sys/xen/xenstore/xenstore.c
--- /var/tmp/freebsd-src/usr/src/sys/xen/xenstore/xenstore.c 2016-03-25 09:09:47.000000000 +0800
+++ freebsd-10.3/usr/src/sys/xen/xenstore/xenstore.c 2017-07-24 14:04:44.885124502 +0800
@@ -1657,3 +1657,20 @@
sx_xunlock(&xs.xenwatch_mutex);
}
}
+
+void
+xs_lock(void)
+{
+
+ sx_xlock(&xs.request_mutex);
+ return;
+}
+
+void
+xs_unlock(void)
+{
+
+ sx_xunlock(&xs.request_mutex);
+ return;
+}
+
diff -ru --exclude-from freebsd-src-diff-exclude-names /var/tmp/freebsd-src/usr/src/sys/xen/xenstore/xenstorevar.h freebsd-10.3/usr/src/sys/xen/xenstore/xenstorevar.h
--- /var/tmp/freebsd-src/usr/src/sys/xen/xenstore/xenstorevar.h 2016-03-25 09:09:47.000000000 +0800
+++ freebsd-10.3/usr/src/sys/xen/xenstore/xenstorevar.h 2017-07-24 14:04:44.892124545 +0800
@@ -338,4 +338,15 @@
*/
struct sbuf *xs_join(const char *, const char *);
+/**
+ * Lock the xenstore request mutex.
+ */
+void xs_lock(void);
+
+/**
+ * Unlock the xenstore request mutex.
+ */
+void xs_unlock(void);
+
#endif /* _XEN_XENSTORE_XENSTOREVAR_H */
+