| 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 */ |
| + |