virtio: add and use virtio_set_features
vdev->guest_features is not masking features that are not supported by the guest. Fix this by introducing a common wrapper to be used by all virtio bus implementations. Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
This commit is contained in:
		
							parent
							
								
									ae0f940e6b
								
							
						
					
					
						commit
						ad0c93328d
					
				| @ -254,10 +254,7 @@ void s390_virtio_device_update_status(VirtIOS390Device *dev) | ||||
|     /* Update guest supported feature bitmap */ | ||||
| 
 | ||||
|     features = bswap32(ldl_be_phys(dev->feat_offs)); | ||||
|     if (vdev->set_features) { | ||||
|         vdev->set_features(vdev, features); | ||||
|     } | ||||
|     vdev->guest_features = features; | ||||
|     virtio_set_features(vdev, features); | ||||
| } | ||||
| 
 | ||||
| VirtIOS390Device *s390_virtio_bus_console(VirtIOS390Bus *bus) | ||||
|  | ||||
| @ -131,9 +131,7 @@ static void syborg_virtio_writel(void *opaque, target_phys_addr_t offset, | ||||
|     } | ||||
|     switch (offset >> 2) { | ||||
|     case SYBORG_VIRTIO_GUEST_FEATURES: | ||||
|         if (vdev->set_features) | ||||
|             vdev->set_features(vdev, value); | ||||
|         vdev->guest_features = value; | ||||
|         virtio_set_features(vdev, value); | ||||
|         break; | ||||
|     case SYBORG_VIRTIO_QUEUE_BASE: | ||||
|         if (value == 0) | ||||
|  | ||||
| @ -285,14 +285,9 @@ static void virtio_ioport_write(void *opaque, uint32_t addr, uint32_t val) | ||||
|     case VIRTIO_PCI_GUEST_FEATURES: | ||||
| 	/* Guest does not negotiate properly?  We have to assume nothing. */ | ||||
| 	if (val & (1 << VIRTIO_F_BAD_FEATURE)) { | ||||
| 	    if (vdev->bad_features) | ||||
| 		val = proxy->host_features & vdev->bad_features(vdev); | ||||
| 	    else | ||||
| 		val = 0; | ||||
|             val = vdev->bad_features ? vdev->bad_features(vdev) : 0; | ||||
| 	} | ||||
|         if (vdev->set_features) | ||||
|             vdev->set_features(vdev, val); | ||||
|         vdev->guest_features = val; | ||||
|         virtio_set_features(vdev, val); | ||||
|         break; | ||||
|     case VIRTIO_PCI_QUEUE_PFN: | ||||
|         pa = (target_phys_addr_t)val << VIRTIO_PCI_QUEUE_ADDR_SHIFT; | ||||
|  | ||||
							
								
								
									
										24
									
								
								hw/virtio.c
									
									
									
									
									
								
							
							
						
						
									
										24
									
								
								hw/virtio.c
									
									
									
									
									
								
							| @ -763,12 +763,25 @@ void virtio_save(VirtIODevice *vdev, QEMUFile *f) | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| int virtio_set_features(VirtIODevice *vdev, uint32_t val) | ||||
| { | ||||
|     uint32_t supported_features = | ||||
|         vdev->binding->get_features(vdev->binding_opaque); | ||||
|     bool bad = (val & ~supported_features) != 0; | ||||
| 
 | ||||
|     val &= supported_features; | ||||
|     if (vdev->set_features) { | ||||
|         vdev->set_features(vdev, val); | ||||
|     } | ||||
|     vdev->guest_features = val; | ||||
|     return bad ? -1 : 0; | ||||
| } | ||||
| 
 | ||||
| int virtio_load(VirtIODevice *vdev, QEMUFile *f) | ||||
| { | ||||
|     int num, i, ret; | ||||
|     uint32_t features; | ||||
|     uint32_t supported_features = | ||||
|         vdev->binding->get_features(vdev->binding_opaque); | ||||
|     uint32_t supported_features; | ||||
| 
 | ||||
|     if (vdev->binding->load_config) { | ||||
|         ret = vdev->binding->load_config(vdev->binding_opaque, f); | ||||
| @ -780,14 +793,13 @@ int virtio_load(VirtIODevice *vdev, QEMUFile *f) | ||||
|     qemu_get_8s(f, &vdev->isr); | ||||
|     qemu_get_be16s(f, &vdev->queue_sel); | ||||
|     qemu_get_be32s(f, &features); | ||||
|     if (features & ~supported_features) { | ||||
| 
 | ||||
|     if (virtio_set_features(vdev, features) < 0) { | ||||
|         supported_features = vdev->binding->get_features(vdev->binding_opaque); | ||||
|         error_report("Features 0x%x unsupported. Allowed features: 0x%x", | ||||
|                      features, supported_features); | ||||
|         return -1; | ||||
|     } | ||||
|     if (vdev->set_features) | ||||
|         vdev->set_features(vdev, features); | ||||
|     vdev->guest_features = features; | ||||
|     vdev->config_len = qemu_get_be32(f); | ||||
|     qemu_get_buffer(f, vdev->config, vdev->config_len); | ||||
| 
 | ||||
|  | ||||
| @ -185,6 +185,7 @@ void virtio_queue_set_vector(VirtIODevice *vdev, int n, uint16_t vector); | ||||
| void virtio_set_status(VirtIODevice *vdev, uint8_t val); | ||||
| void virtio_reset(void *opaque); | ||||
| void virtio_update_irq(VirtIODevice *vdev); | ||||
| int virtio_set_features(VirtIODevice *vdev, uint32_t val); | ||||
| 
 | ||||
| void virtio_bind_device(VirtIODevice *vdev, const VirtIOBindings *binding, | ||||
|                         void *opaque); | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Paolo Bonzini
						Paolo Bonzini