blob: 51d5fb410c6e5be934fe14c272a71a409b0d3036 [file] [log] [blame]
/*
* Copyright © 2023 Google, LLC
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*/
#include "lvp_fuchsia_memory.h"
#include <zircon/process.h>
#include <zircon/syscalls.h>
#include <assert.h>
#include <stdio.h>
#include "lvp_private.h"
VkResult lvp_fuchsia_map_vmo(zx_handle_t vmo, size_t len, zx_vaddr_t* ptr)
{
zx_status_t status = zx_vmar_map(zx_vmar_root_self(), ZX_VM_PERM_READ | ZX_VM_PERM_WRITE,
/*vmar_offset=*/ 0, vmo, /*vmo_offset=*/0, len, ptr);
switch (status) {
case ZX_OK:
return VK_SUCCESS;
case ZX_ERR_BAD_HANDLE:
return VK_ERROR_INITIALIZATION_FAILED;
case ZX_ERR_NO_RESOURCES:
case ZX_ERR_BUFFER_TOO_SMALL:
case ZX_ERR_NO_MEMORY:
zx_handle_close(vmo);
return VK_ERROR_OUT_OF_HOST_MEMORY;
default:
zx_handle_close(vmo);
return VK_ERROR_UNKNOWN;
}
}
VkResult lvp_fuchsia_get_vmo_size(zx_handle_t vmo, uint64_t* size_out)
{
/* TODO(https://fxbug.dev/321122796):
Revisit this in the context of RFC-0238, which deprecates ZX_PROP_VMO_CONTENT_SIZE. */
VkResult error = VK_SUCCESS;
zx_status_t status = zx_object_get_property(vmo, ZX_PROP_VMO_CONTENT_SIZE,
size_out, sizeof(*size_out));
switch (status) {
case ZX_OK:
break;
case ZX_ERR_ACCESS_DENIED:
/* If no content size is specified, we instead use `zx_vmo_get_size()`. Note the RFC-0238
comment above. */
status = zx_vmo_get_size(vmo, size_out);
if (status != ZX_OK) {
zx_handle_close(vmo);
fprintf(stderr,
"lvp_fuchsia_get_vmo_size(): zx_vmo_get_size failed with status: %d\n", status);
return VK_ERROR_UNKNOWN;
}
break;
case ZX_ERR_BAD_HANDLE:
return VK_ERROR_INVALID_EXTERNAL_HANDLE;
case ZX_ERR_WRONG_TYPE:
zx_handle_close(vmo);
return VK_ERROR_INVALID_EXTERNAL_HANDLE;
case ZX_ERR_NO_MEMORY:
zx_handle_close(vmo);
return VK_ERROR_OUT_OF_HOST_MEMORY;
default:
/* This is not an expected return value from `zx_object_get_property()`. */
assert(false);
return VK_ERROR_UNKNOWN;
}
return VK_SUCCESS;
}
VkResult lvp_fuchsia_import_vmo(
zx_handle_t vmo,
uint64_t allocation_size,
struct lvp_device_memory* memory_out)
{
uint64_t vmo_size = 0;
VkResult error = lvp_fuchsia_get_vmo_size(vmo, &vmo_size);
if (error != VK_SUCCESS)
return error;
assert(vmo_size >= allocation_size);
zx_vaddr_t vmo_ptr = 0;
error = lvp_fuchsia_map_vmo(vmo, allocation_size, &vmo_ptr);
if (error != VK_SUCCESS)
return error;
memory_out->pmem = (void*)vmo_ptr;
/* TODO(https://fxbug.dev/321122796): do we need a different memory type to distinguish VMOs
obtained from a sysmem buffer collection? */
memory_out->memory_type = LVP_DEVICE_MEMORY_TYPE_ZIRCON_VMO;
memory_out->map_size = allocation_size;
memory_out->vmo_handle = vmo;
memory_out->map = (void*)vmo_ptr;
return VK_SUCCESS;
}