blob: c6f745a52191b4e52a3cc953d23e3907a4e774fc [file] [log] [blame]
/*
* Copyright 2019 The Hafnium Authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "hf/spci.h"
#include "hf/types.h"
/*
* Copied from hf/arch/std.h because we can't include Hafnium internal headers
* here.
*/
#ifndef align_up
#define align_up(v, a) (((uintptr_t)(v) + ((a)-1)) & ~((a)-1))
#endif
/**
* Initialises the given `spci_memory_region` and copies the constituent
* information to it. Returns the length in bytes occupied by the data copied to
* `memory_region` (attributes, constituents and memory region header size).
*/
uint32_t spci_memory_region_init(
struct spci_memory_region *memory_region, spci_vm_id_t sender, spci_vm_id_t receiver,
const struct spci_memory_region_constituent constituents[],
uint32_t constituent_count, uint32_t tag, spci_memory_region_flags_t flags,
enum spci_memory_access access, enum spci_memory_type type,
enum spci_memory_cacheability cacheability,
enum spci_memory_shareability shareability)
{
uint32_t constituents_length =
constituent_count *
sizeof(struct spci_memory_region_constituent);
uint32_t index;
struct spci_memory_region_constituent *region_constituents;
uint16_t attributes = 0;
/* Set memory region's page attributes. */
spci_set_memory_access_attr(&attributes, access);
spci_set_memory_type_attr(&attributes, type);
spci_set_memory_cacheability_attr(&attributes, cacheability);
spci_set_memory_shareability_attr(&attributes, shareability);
memory_region->tag = tag;
memory_region->flags = flags;
memory_region->sender = sender;
memory_region->reserved = 0;
memory_region->page_count = 0;
memory_region->constituent_count = constituent_count;
memory_region->attribute_count = 1;
memory_region->attributes[0].receiver = receiver;
memory_region->attributes[0].memory_attributes = attributes;
/*
* Constituent offset must be aligned to a 64-bit boundary so that
* 64-bit addresses can be copied without alignment faults.
*/
memory_region->constituent_offset = align_up(
sizeof(struct spci_memory_region) +
memory_region->attribute_count *
sizeof(struct spci_memory_region_attributes),
8);
region_constituents =
spci_memory_region_get_constituents(memory_region);
for (index = 0; index < constituent_count; index++) {
region_constituents[index] = constituents[index];
region_constituents[index].reserved = 0;
memory_region->page_count += constituents[index].page_count;
}
/*
* TODO: Add assert ensuring that the specified message
* length is not greater than SPCI_MSG_PAYLOAD_MAX.
*/
return memory_region->constituent_offset + constituents_length;
}