diff options
author | Gurchetan Singh <gurchetansingh@chromium.org> | 2020-01-22 17:59:22 -0800 |
---|---|---|
committer | Commit Bot <commit-bot@chromium.org> | 2020-03-23 20:37:12 +0000 |
commit | 83fc5c49ba930a62ef1f4d93bc2004d779b6d16f (patch) | |
tree | 514d89cc061e6b34acaf5cbe10c254368729976a | |
parent | 151af70ac9778f5247f6fd58fe8b20c089604429 (diff) | |
download | crosvm-83fc5c49ba930a62ef1f4d93bc2004d779b6d16f.tar crosvm-83fc5c49ba930a62ef1f4d93bc2004d779b6d16f.tar.gz crosvm-83fc5c49ba930a62ef1f4d93bc2004d779b6d16f.tar.bz2 crosvm-83fc5c49ba930a62ef1f4d93bc2004d779b6d16f.tar.lz crosvm-83fc5c49ba930a62ef1f4d93bc2004d779b6d16f.tar.xz crosvm-83fc5c49ba930a62ef1f4d93bc2004d779b6d16f.tar.zst crosvm-83fc5c49ba930a62ef1f4d93bc2004d779b6d16f.zip |
devices: gpu: complete resource V2 rebase
* Remove RESOURCE_V2_UNREF * Add RESOURCE_MAP/RESOURCE_UNMAP to enable resources without guest storage that don't need to be mapped directly either BUG=chromium:924405 TEST=compile and test Change-Id: I10d6cd120d86131fa7ed8917ddad25cdb99ae50c Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/crosvm/+/2015587 Tested-by: Gurchetan Singh <gurchetansingh@chromium.org> Auto-Submit: Gurchetan Singh <gurchetansingh@chromium.org> Reviewed-by: Zach Reizner <zachr@chromium.org> Commit-Queue: Gurchetan Singh <gurchetansingh@chromium.org>
-rw-r--r-- | devices/src/virtio/gpu/mod.rs | 18 | ||||
-rw-r--r-- | devices/src/virtio/gpu/protocol.rs | 34 | ||||
-rw-r--r-- | devices/src/virtio/gpu/virtio_3d_backend.rs | 216 | ||||
-rw-r--r-- | vm_control/src/lib.rs | 9 |
4 files changed, 164 insertions, 113 deletions
diff --git a/devices/src/virtio/gpu/mod.rs b/devices/src/virtio/gpu/mod.rs index d211768..93d004f 100644 --- a/devices/src/virtio/gpu/mod.rs +++ b/devices/src/virtio/gpu/mod.rs @@ -284,14 +284,17 @@ trait Backend { _flags: u32, _size: u64, _memory_id: u64, - _pci_addr: u64, _vecs: Vec<(GuestAddress, usize)>, _mem: &GuestMemory, ) -> GpuResponse { GpuResponse::ErrUnspec } - fn resource_v2_unref(&mut self, _resource_id: u32) -> GpuResponse { + fn resource_map(&mut self, _resource_id: u32, _pci_addr: u64) -> GpuResponse { + GpuResponse::ErrUnspec + } + + fn resource_unmap(&mut self, _resource_id: u32) -> GpuResponse { GpuResponse::ErrUnspec } } @@ -606,7 +609,6 @@ impl Frontend { let ctx_id = info.hdr.ctx_id.to_native(); let flags = info.flags.to_native(); let size = info.size.to_native(); - let pci_addr = info.pci_addr.to_native(); let memory_id = info.memory_id.to_native(); let entry_count = info.nr_entries.to_native(); if entry_count > VIRTIO_GPU_MAX_IOVEC_ENTRIES @@ -632,15 +634,19 @@ impl Frontend { ctx_id, flags, size, - pci_addr, memory_id, vecs, mem, ) } - GpuCommand::ResourceV2Unref(info) => { + GpuCommand::ResourceMap(info) => { + let resource_id = info.resource_id.to_native(); + let offset = info.offset.to_native(); + self.backend.resource_map(resource_id, offset) + } + GpuCommand::ResourceUnmap(info) => { let resource_id = info.resource_id.to_native(); - self.backend.resource_v2_unref(resource_id) + self.backend.resource_unmap(resource_id) } } } diff --git a/devices/src/virtio/gpu/protocol.rs b/devices/src/virtio/gpu/protocol.rs index 0563c1b..c98e289 100644 --- a/devices/src/virtio/gpu/protocol.rs +++ b/devices/src/virtio/gpu/protocol.rs @@ -50,7 +50,8 @@ pub const VIRTIO_GPU_CMD_TRANSFER_FROM_HOST_3D: u32 = 0x206; pub const VIRTIO_GPU_CMD_SUBMIT_3D: u32 = 0x207; /* The following hypercalls are not upstreamed. */ pub const VIRTIO_GPU_CMD_RESOURCE_CREATE_V2: u32 = 0x208; -pub const VIRTIO_GPU_CMD_RESOURCE_CREATE_V2_UNREF: u32 = 0x209; +pub const VIRTIO_GPU_CMD_RESOURCE_MAP: u32 = 0x209; +pub const VIRTIO_GPU_CMD_RESOURCE_UNMAP: u32 = 0x20a; /* cursor commands */ pub const VIRTIO_GPU_CMD_UPDATE_CURSOR: u32 = 0x300; @@ -113,7 +114,8 @@ pub fn virtio_gpu_cmd_str(cmd: u32) -> &'static str { VIRTIO_GPU_CMD_TRANSFER_FROM_HOST_3D => "VIRTIO_GPU_CMD_TRANSFER_FROM_HOST_3D", VIRTIO_GPU_CMD_SUBMIT_3D => "VIRTIO_GPU_CMD_SUBMIT_3D", VIRTIO_GPU_CMD_RESOURCE_CREATE_V2 => "VIRTIO_GPU_CMD_RESOURCE_CREATE_V2", - VIRTIO_GPU_CMD_RESOURCE_CREATE_V2_UNREF => "VIRTIO_GPU_CMD_RESOURCE_CREATE_V2_UNREF", + VIRTIO_GPU_CMD_RESOURCE_MAP => "VIRTIO_GPU_RESOURCE_MAP", + VIRTIO_GPU_CMD_RESOURCE_UNMAP => "VIRTIO_GPU_RESOURCE_UNMAP", VIRTIO_GPU_CMD_UPDATE_CURSOR => "VIRTIO_GPU_CMD_UPDATE_CURSOR", VIRTIO_GPU_CMD_MOVE_CURSOR => "VIRTIO_GPU_CMD_MOVE_CURSOR", VIRTIO_GPU_RESP_OK_NODATA => "VIRTIO_GPU_RESP_OK_NODATA", @@ -502,7 +504,6 @@ pub struct virtio_gpu_resource_create_v2 { pub resource_id: Le32, pub flags: Le32, pub size: Le64, - pub pci_addr: Le64, pub memory_id: Le64, pub nr_entries: Le32, pub padding: Le32, @@ -512,13 +513,24 @@ unsafe impl DataInit for virtio_gpu_resource_create_v2 {} #[derive(Copy, Clone, Debug, Default)] #[repr(C)] -pub struct virtio_gpu_resource_v2_unref { +pub struct virtio_gpu_resource_map { + pub hdr: virtio_gpu_ctrl_hdr, + pub resource_id: Le32, + pub map_flags: Le32, + pub offset: Le64, +} + +unsafe impl DataInit for virtio_gpu_resource_map {} + +#[derive(Copy, Clone, Debug, Default)] +#[repr(C)] +pub struct virtio_gpu_resource_unmap { pub hdr: virtio_gpu_ctrl_hdr, pub resource_id: Le32, pub padding: Le32, } -unsafe impl DataInit for virtio_gpu_resource_v2_unref {} +unsafe impl DataInit for virtio_gpu_resource_unmap {} /* simple formats for fbcon/X use */ pub const VIRTIO_GPU_FORMAT_B8G8R8A8_UNORM: u32 = 1; @@ -552,7 +564,8 @@ pub enum GpuCommand { TransferFromHost3d(virtio_gpu_transfer_host_3d), CmdSubmit3d(virtio_gpu_cmd_submit), ResourceCreateV2(virtio_gpu_resource_create_v2), - ResourceV2Unref(virtio_gpu_resource_v2_unref), + ResourceMap(virtio_gpu_resource_map), + ResourceUnmap(virtio_gpu_resource_unmap), UpdateCursor(virtio_gpu_update_cursor), MoveCursor(virtio_gpu_update_cursor), } @@ -620,7 +633,8 @@ impl fmt::Debug for GpuCommand { TransferFromHost3d(_info) => f.debug_struct("TransferFromHost3d").finish(), CmdSubmit3d(_info) => f.debug_struct("CmdSubmit3d").finish(), ResourceCreateV2(_info) => f.debug_struct("ResourceCreateV2").finish(), - ResourceV2Unref(_info) => f.debug_struct("ResourceV2Unref").finish(), + ResourceMap(_info) => f.debug_struct("ResourceMap").finish(), + ResourceUnmap(_info) => f.debug_struct("ResourceUnmap").finish(), UpdateCursor(_info) => f.debug_struct("UpdateCursor").finish(), MoveCursor(_info) => f.debug_struct("MoveCursor").finish(), } @@ -652,7 +666,8 @@ impl GpuCommand { VIRTIO_GPU_CMD_TRANSFER_FROM_HOST_3D => TransferFromHost3d(cmd.read_obj()?), VIRTIO_GPU_CMD_SUBMIT_3D => CmdSubmit3d(cmd.read_obj()?), VIRTIO_GPU_CMD_RESOURCE_CREATE_V2 => ResourceCreateV2(cmd.read_obj()?), - VIRTIO_GPU_CMD_RESOURCE_CREATE_V2_UNREF => ResourceV2Unref(cmd.read_obj()?), + VIRTIO_GPU_CMD_RESOURCE_MAP => ResourceMap(cmd.read_obj()?), + VIRTIO_GPU_CMD_RESOURCE_UNMAP => ResourceUnmap(cmd.read_obj()?), VIRTIO_GPU_CMD_UPDATE_CURSOR => UpdateCursor(cmd.read_obj()?), VIRTIO_GPU_CMD_MOVE_CURSOR => MoveCursor(cmd.read_obj()?), _ => return Err(GpuCommandDecodeError::InvalidType(hdr.type_.into())), @@ -682,7 +697,8 @@ impl GpuCommand { TransferFromHost3d(info) => &info.hdr, CmdSubmit3d(info) => &info.hdr, ResourceCreateV2(info) => &info.hdr, - ResourceV2Unref(info) => &info.hdr, + ResourceMap(info) => &info.hdr, + ResourceUnmap(info) => &info.hdr, UpdateCursor(info) => &info.hdr, MoveCursor(info) => &info.hdr, } diff --git a/devices/src/virtio/gpu/virtio_3d_backend.rs b/devices/src/virtio/gpu/virtio_3d_backend.rs index 21b5bf4..3ede8a6 100644 --- a/devices/src/virtio/gpu/virtio_3d_backend.rs +++ b/devices/src/virtio/gpu/virtio_3d_backend.rs @@ -44,6 +44,8 @@ struct Virtio3DResource { gpu_resource: GpuRendererResource, display_import: Option<(Rc<RefCell<GpuDisplay>>, u32)>, kvm_slot: Option<u32>, + size: u64, + flags: u32, } impl Virtio3DResource { @@ -54,27 +56,38 @@ impl Virtio3DResource { gpu_resource, display_import: None, kvm_slot: None, + flags: 0, + // The size of the host resource isn't really zero, but it's undefined by + // virtio_gpu_resource_create_3d + size: 0, } } pub fn v2_new( width: u32, height: u32, - kvm_slot: u32, gpu_resource: GpuRendererResource, + flags: u32, + size: u64, ) -> Virtio3DResource { Virtio3DResource { width, height, gpu_resource, display_import: None, - kvm_slot: Some(kvm_slot), + kvm_slot: None, + flags, + size, } } fn as_mut(&mut self) -> &mut dyn VirtioResource { self } + + fn use_flags(&self) -> u32 { + self.flags & VIRTIO_GPU_RESOURCE_USE_MASK + } } impl VirtioResource for Virtio3DResource { @@ -765,7 +778,6 @@ impl Backend for Virtio3DBackend { ctx_id: u32, flags: u32, size: u64, - pci_addr: u64, memory_id: u64, vecs: Vec<(GuestAddress, usize)>, mem: &GuestMemory, @@ -788,103 +800,119 @@ impl Backend for Virtio3DBackend { } }; - let use_flags = VIRTIO_GPU_RESOURCE_USE_MASK & flags; - match use_flags { - VIRTIO_GPU_RESOURCE_USE_MAPPABLE => { - let dma_buf_fd = match resource.export() { - Ok(export) => export.1, - Err(e) => { - error!("failed to export plane fd: {}", e); - return GpuResponse::ErrUnspec; - } - }; - - let request = VmMemoryRequest::RegisterMemoryAtAddress( - self.pci_bar, - MaybeOwnedFd::Borrowed(dma_buf_fd.as_raw_fd()), - size as usize, - pci_addr, - ); - - match self.gpu_device_socket.send(&request) { - Ok(_resq) => match self.gpu_device_socket.recv() { - Ok(response) => match response { - VmMemoryResponse::RegisterMemory { pfn: _, slot } => { - entry.insert(Virtio3DResource::v2_new( - self.base.display_width, - self.base.display_height, - slot, - resource, - )); - GpuResponse::OkNoData - } - VmMemoryResponse::Err(e) => { - error!("received an error: {}", e); - GpuResponse::ErrUnspec - } - _ => { - error!("recieved an unexpected response"); - GpuResponse::ErrUnspec - } - }, - Err(e) => { - error!("failed to receive data: {}", e); - GpuResponse::ErrUnspec - } - }, - Err(e) => { - error!("failed to send request: {}", e); - GpuResponse::ErrUnspec - } - } - } - _ => { - entry.insert(Virtio3DResource::new( - self.base.display_width, - self.base.display_height, - resource, - )); + entry.insert(Virtio3DResource::v2_new( + self.base.display_width, + self.base.display_height, + resource, + flags, + size, + )); - GpuResponse::OkNoData - } - } + GpuResponse::OkNoData } Entry::Occupied(_) => GpuResponse::ErrInvalidResourceId, } } - fn resource_v2_unref(&mut self, resource_id: u32) -> GpuResponse { - match self.resources.remove(&resource_id) { - Some(entry) => match entry.kvm_slot { - Some(kvm_slot) => { - let request = VmMemoryRequest::UnregisterMemory(kvm_slot); - match self.gpu_device_socket.send(&request) { - Ok(_resq) => match self.gpu_device_socket.recv() { - Ok(response) => match response { - VmMemoryResponse::Ok => GpuResponse::OkNoData, - VmMemoryResponse::Err(e) => { - error!("received an error: {}", e); - GpuResponse::ErrUnspec - } - _ => { - error!("recieved an unexpected response"); - GpuResponse::ErrUnspec - } - }, - Err(e) => { - error!("failed to receive data: {}", e); - GpuResponse::ErrUnspec - } - }, - Err(e) => { - error!("failed to send request: {}", e); - GpuResponse::ErrUnspec - } - } - } - None => GpuResponse::OkNoData, - }, - None => GpuResponse::ErrInvalidResourceId, + fn resource_map(&mut self, resource_id: u32, offset: u64) -> GpuResponse { + let resource = match self.resources.get_mut(&resource_id) { + Some(r) => r, + None => return GpuResponse::ErrInvalidResourceId, + }; + + if resource.use_flags() & VIRTIO_GPU_RESOURCE_USE_MAPPABLE == 0 { + error!("resource not mappable"); + return GpuResponse::ErrUnspec; + } + + let dma_buf_fd = match resource.gpu_resource.export() { + Ok(export) => export.1, + Err(e) => { + error!("failed to export plane fd: {}", e); + return GpuResponse::ErrUnspec; + } + }; + + let request = VmMemoryRequest::RegisterFdAtPciBarOffset( + self.pci_bar, + MaybeOwnedFd::Borrowed(dma_buf_fd.as_raw_fd()), + resource.size as usize, + offset, + ); + + match self.gpu_device_socket.send(&request) { + Ok(_) => (), + Err(e) => { + error!("failed to send request: {}", e); + return GpuResponse::ErrUnspec; + } + } + + let response = match self.gpu_device_socket.recv() { + Ok(response) => response, + Err(e) => { + error!("failed to receive data: {}", e); + return GpuResponse::ErrUnspec; + } + }; + + match response { + VmMemoryResponse::RegisterMemory { pfn: _, slot } => { + resource.kvm_slot = Some(slot); + GpuResponse::OkNoData + } + VmMemoryResponse::Err(e) => { + error!("received an error: {}", e); + GpuResponse::ErrUnspec + } + _ => { + error!("recieved an unexpected response"); + GpuResponse::ErrUnspec + } + } + } + + fn resource_unmap(&mut self, resource_id: u32) -> GpuResponse { + let resource = match self.resources.get_mut(&resource_id) { + Some(r) => r, + None => return GpuResponse::ErrInvalidResourceId, + }; + + let kvm_slot = match resource.kvm_slot { + Some(kvm_slot) => kvm_slot, + None => return GpuResponse::ErrUnspec, + }; + + let request = VmMemoryRequest::UnregisterMemory(kvm_slot); + match self.gpu_device_socket.send(&request) { + Ok(_) => (), + Err(e) => { + error!("failed to send request: {}", e); + return GpuResponse::ErrUnspec; + } + } + + let response = match self.gpu_device_socket.recv() { + Ok(response) => response, + Err(e) => { + error!("failed to receive data: {}", e); + return GpuResponse::ErrUnspec; + } + }; + + match response { + VmMemoryResponse::Ok => { + resource.kvm_slot = None; + GpuResponse::OkNoData + } + VmMemoryResponse::Err(e) => { + error!("received an error: {}", e); + GpuResponse::ErrUnspec + } + _ => { + error!("recieved an unexpected response"); + GpuResponse::ErrUnspec + } } } } diff --git a/vm_control/src/lib.rs b/vm_control/src/lib.rs index 298d800..b2577d9 100644 --- a/vm_control/src/lib.rs +++ b/vm_control/src/lib.rs @@ -192,7 +192,7 @@ pub enum VmMemoryRequest { RegisterMemory(MaybeOwnedFd, usize), /// Similiar to `VmMemoryRequest::RegisterMemory`, but doesn't allocate new address space. /// Useful for cases where the address space is already allocated (PCI regions). - RegisterMemoryAtAddress(Alloc, MaybeOwnedFd, usize, u64), + RegisterFdAtPciBarOffset(Alloc, MaybeOwnedFd, usize, u64), /// Unregister the given memory slot that was previously registereed with `RegisterMemory`. UnregisterMemory(u32), /// Allocate GPU buffer of a given size/format and register the memory into guest address space. @@ -230,8 +230,8 @@ impl VmMemoryRequest { Err(e) => VmMemoryResponse::Err(e), } } - RegisterMemoryAtAddress(alloc, ref fd, size, guest_addr) => { - match register_memory(vm, sys_allocator, fd, size, Some((alloc, guest_addr))) { + RegisterFdAtPciBarOffset(alloc, ref fd, size, offset) => { + match register_memory(vm, sys_allocator, fd, size, Some((alloc, offset))) { Ok((pfn, slot)) => VmMemoryResponse::RegisterMemory { pfn, slot }, Err(e) => VmMemoryResponse::Err(e), } @@ -433,12 +433,13 @@ fn register_memory( }; let addr = match allocation { - Some((Alloc::PciBar { bus, dev, bar }, address)) => { + Some((Alloc::PciBar { bus, dev, bar }, offset)) => { match allocator .mmio_allocator(MmioType::High) .get(&Alloc::PciBar { bus, dev, bar }) { Some((start_addr, length, _)) => { + let address = *start_addr + offset; let range = *start_addr..*start_addr + *length; let end = address + (size as u64); match (range.contains(&address), range.contains(&end)) { |