blob: 942879a984febeb2ee9eb41fceeb8bc67b88be61 [file] [log] [blame]
// Copyright 2019 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "magma.h"
#include <sys/mman.h>
#include <vector>
#include "src/graphics/lib/magma/include/virtio/virtio_magma.h"
#include "src/graphics/lib/magma/src/libmagma_linux/virtmagma_util.h"
// TODO(MA-623): support an object that is a parent of magma_connection_t
// This class is a temporary workaround to support magma APIs that do not
// pass in generic objects capable of holding file descriptors, e.g.
// magma_duplicate_handle.
std::map<uint32_t, virtmagma_handle_t*>& GlobalHandleTable() {
static std::map<uint32_t, virtmagma_handle_t*> ht;
return ht;
}
magma_status_t magma_map(magma_connection_t connection, magma_buffer_t buffer, void** addr_out) {
*addr_out = nullptr;
auto connection_wrapped = virtmagma_connection_t::Get(connection);
connection = connection_wrapped->Object();
int32_t file_descriptor = connection_wrapped->Parent().first;
int32_t file_descriptor_mmap = connection_wrapped->Parent().second;
auto buffer_wrapped = virtmagma_buffer_t::Get(buffer);
buffer = buffer_wrapped->Object();
virtio_magma_map_ctrl_t request{};
struct {
virtio_magma_map_resp_t virtio_response;
size_t size_to_mmap_out;
} response{};
request.hdr.type = VIRTIO_MAGMA_CMD_MAP;
request.connection = reinterpret_cast<decltype(request.connection)>(connection);
request.buffer = reinterpret_cast<decltype(request.buffer)>(buffer);
if (!virtmagma_send_command(file_descriptor, &request, sizeof(request), &response,
sizeof(response))) {
return MAGMA_STATUS_INTERNAL_ERROR;
}
if (response.virtio_response.hdr.type != VIRTIO_MAGMA_RESP_MAP) {
return MAGMA_STATUS_INTERNAL_ERROR;
}
// The only simple way to construct a new vm_area_struct in the kernel is to reuse
// the mmap call path.
void* mapped_addr = mmap(nullptr, response.size_to_mmap_out, PROT_READ | PROT_WRITE, MAP_SHARED,
file_descriptor_mmap, 0);
if (mapped_addr == MAP_FAILED) {
return MAGMA_STATUS_INTERNAL_ERROR;
}
*addr_out = mapped_addr;
magma_status_t result_return =
static_cast<decltype(result_return)>(response.virtio_response.result_return);
return result_return;
}
magma_status_t magma_map_aligned(magma_connection_t connection, magma_buffer_t buffer,
uint64_t alignment, void** addr_out) {
*addr_out = nullptr;
return MAGMA_STATUS_UNIMPLEMENTED;
}
magma_status_t magma_map_specific(magma_connection_t connection, magma_buffer_t buffer,
uint64_t addr, uint64_t offset, uint64_t length) {
return MAGMA_STATUS_UNIMPLEMENTED;
}
magma_status_t magma_wait_semaphores(const magma_semaphore_t* semaphores, uint32_t count,
uint64_t timeout_ms, magma_bool_t wait_all) {
if (count == 0)
return MAGMA_STATUS_OK;
auto semaphore0_wrapped = virtmagma_semaphore_t::Get(semaphores[0]);
auto semaphore0_parent_wrapped = virtmagma_connection_t::Get(semaphore0_wrapped->Parent());
int32_t file_descriptor = semaphore0_parent_wrapped->Parent().first;
virtio_magma_wait_semaphores_ctrl_t request{};
virtio_magma_wait_semaphores_resp_t response{};
request.hdr.type = VIRTIO_MAGMA_CMD_WAIT_SEMAPHORES;
std::vector<magma_semaphore_t> unwrapped_semaphores(count);
for (uint32_t i = 0; i < count; ++i) {
unwrapped_semaphores[i] = virtmagma_semaphore_t::Get(semaphores[i])->Object();
}
request.semaphores = reinterpret_cast<decltype(request.semaphores)>(unwrapped_semaphores.data());
request.count = count;
request.timeout_ms = timeout_ms;
request.wait_all = wait_all;
if (!virtmagma_send_command(file_descriptor, &request, sizeof(request), &response,
sizeof(response)))
return MAGMA_STATUS_INTERNAL_ERROR;
if (response.hdr.type != VIRTIO_MAGMA_RESP_WAIT_SEMAPHORES)
return MAGMA_STATUS_INTERNAL_ERROR;
magma_status_t result_return = static_cast<decltype(result_return)>(response.result_return);
return result_return;
}
magma_status_t magma_poll(magma_poll_item_t* items, uint32_t count, uint64_t timeout_ns) {
return MAGMA_STATUS_UNIMPLEMENTED;
}
void magma_execute_command_buffer_with_resources(magma_connection_t connection, uint32_t context_id,
struct magma_system_command_buffer* command_buffer,
struct magma_system_exec_resource* resources,
uint64_t* semaphore_ids) {
virtmagma_command_buffer virt_command_buffer;
virt_command_buffer.command_buffer_size = sizeof(magma_system_command_buffer);
virt_command_buffer.command_buffer =
reinterpret_cast<decltype(virt_command_buffer.command_buffer)>(command_buffer);
virt_command_buffer.resource_size =
sizeof(magma_system_exec_resource) * command_buffer->num_resources;
virt_command_buffer.resources =
reinterpret_cast<decltype(virt_command_buffer.resources)>(resources);
virt_command_buffer.semaphore_size = sizeof(uint64_t) * (command_buffer->wait_semaphore_count +
command_buffer->signal_semaphore_count);
virt_command_buffer.semaphores =
reinterpret_cast<decltype(virt_command_buffer.resources)>(semaphore_ids);
virtio_magma_execute_command_buffer_with_resources_ctrl request{};
virtio_magma_execute_command_buffer_with_resources_resp response{};
request.hdr.type = VIRTIO_MAGMA_CMD_EXECUTE_COMMAND_BUFFER_WITH_RESOURCES;
auto connection_wrapped = virtmagma_connection_t::Get(connection);
request.connection = reinterpret_cast<decltype(request.connection)>(connection_wrapped->Object());
request.context_id = context_id;
request.command_buffer = reinterpret_cast<decltype(request.command_buffer)>(&virt_command_buffer);
int32_t file_descriptor = connection_wrapped->Parent().first;
if (!virtmagma_send_command(file_descriptor, &request, sizeof(request), &response,
sizeof(response))) {
assert(false);
}
}
magma_status_t magma_initialize_tracing(magma_handle_t channel) {
return MAGMA_STATUS_UNIMPLEMENTED;
}