/* * The virtio core takes the features the Host offers, and copies the ones * supported by the driver into the vdev->features array. Once that's all * sorted out, this routine is called so we can tell the Host which features we * understand and accept. */ static void lg_finalize_features(struct virtio_device *vdev) { unsigned int i, bits; struct lguest_device_desc *desc = to_lgdev(vdev)->desc; /* Second half of bitmap is features we accept. */ u8 *out_features = lg_features(desc) + desc->feature_len; /* Give virtio_ring a chance to accept features. */ vring_transport_features(vdev); /* * The vdev->feature array is a Linux bitmask: this isn't the same as a * the simple array of bits used by lguest devices for features. So we * do this slow, manual conversion which is completely general. */ memset(out_features, 0, desc->feature_len); bits = min_t(unsigned, desc->feature_len, sizeof(vdev->features)) * 8; for (i = 0; i < bits; i++) { if (test_bit(i, vdev->features)) out_features[i / 8] |= (1 << (i % 8)); } /* Tell Host we've finished with this device's feature negotiation */ status_notify(vdev); }
/* This gets the device's feature bits. */ static u32 lg_get_features(struct virtio_device *vdev) { unsigned int i; u32 features = 0; struct lguest_device_desc *desc = to_lgdev(vdev)->desc; u8 *in_features = lg_features(desc); /* We do this the slow but generic way. */ for (i = 0; i < min(desc->feature_len * 8, 32); i++) if (in_features[i / 8] & (1 << (i % 8))) features |= (1 << i); return features; }
/* This tests (and acknowleges) a feature bit. */ static bool lg_feature(struct virtio_device *vdev, unsigned fbit) { struct lguest_device_desc *desc = to_lgdev(vdev)->desc; u8 *features; /* Obviously if they ask for a feature off the end of our feature * bitmap, it's not set. */ if (fbit / 8 > desc->feature_len) return false; /* The feature bitmap comes after the virtqueues. */ features = lg_features(desc); if (!(features[fbit / 8] & (1 << (fbit % 8)))) return false; /* We set the matching bit in the other half of the bitmap to tell the * Host we want to use this feature. We don't use this yet, but we * could in future. */ features[desc->feature_len + fbit / 8] |= (1 << (fbit % 8)); return true; }
/* The config space comes after the two feature bitmasks. */ static u8 *lg_config(const struct lguest_device_desc *desc) { return lg_features(desc) + desc->feature_len * 2; }