blob: 59c36e4647adc788df9b4b47572e5322c7e07370 [file] [log] [blame]
Andrew Walbran66839252019-11-07 16:01:48 +00001/*
2 * Copyright 2019 The Hafnium Authors.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * https://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "hf/spci.h"
18
19#include "hf/types.h"
20
21/*
22 * Copied from hf/arch/std.h because we can't include Hafnium internal headers
23 * here.
24 */
25#ifndef align_up
26#define align_up(v, a) (((uintptr_t)(v) + ((a)-1)) & ~((a)-1))
27#endif
28
29/**
Andrew Walbran66839252019-11-07 16:01:48 +000030 * Initialises the given `spci_memory_region` and copies the constituent
31 * information to it. Returns the length in bytes occupied by the data copied to
32 * `memory_region` (attributes, constituents and memory region header size).
33 */
34uint32_t spci_memory_region_init(
Andrew Walbrane28f4a22019-12-24 15:45:36 +000035 struct spci_memory_region *memory_region, spci_vm_id_t sender, spci_vm_id_t receiver,
Andrew Walbran66839252019-11-07 16:01:48 +000036 const struct spci_memory_region_constituent constituents[],
Andrew Walbran28b02102019-11-20 18:03:10 +000037 uint32_t constituent_count, uint32_t tag, spci_memory_region_flags_t flags,
Andrew Walbran66839252019-11-07 16:01:48 +000038 enum spci_memory_access access, enum spci_memory_type type,
39 enum spci_memory_cacheability cacheability,
40 enum spci_memory_shareability shareability)
41{
42 uint32_t constituents_length =
43 constituent_count *
44 sizeof(struct spci_memory_region_constituent);
45 uint32_t index;
46 struct spci_memory_region_constituent *region_constituents;
47 uint16_t attributes = 0;
48
49 /* Set memory region's page attributes. */
50 spci_set_memory_access_attr(&attributes, access);
51 spci_set_memory_type_attr(&attributes, type);
52 spci_set_memory_cacheability_attr(&attributes, cacheability);
53 spci_set_memory_shareability_attr(&attributes, shareability);
54
55 memory_region->tag = tag;
Andrew Walbran28b02102019-11-20 18:03:10 +000056 memory_region->flags = flags;
Andrew Walbrane28f4a22019-12-24 15:45:36 +000057 memory_region->sender = sender;
58 memory_region->reserved = 0;
Andrew Walbran66839252019-11-07 16:01:48 +000059 memory_region->page_count = 0;
60 memory_region->constituent_count = constituent_count;
61 memory_region->attribute_count = 1;
62 memory_region->attributes[0].receiver = receiver;
63 memory_region->attributes[0].memory_attributes = attributes;
64
65 /*
Andrew Walbrand88ee922020-01-15 18:13:21 +000066 * Constituent offset must be aligned to a 32-bit boundary so that
67 * 32-bit values can be copied without alignment faults.
Andrew Walbran66839252019-11-07 16:01:48 +000068 */
69 memory_region->constituent_offset = align_up(
70 sizeof(struct spci_memory_region) +
71 memory_region->attribute_count *
72 sizeof(struct spci_memory_region_attributes),
Andrew Walbrand88ee922020-01-15 18:13:21 +000073 4);
Andrew Walbran66839252019-11-07 16:01:48 +000074 region_constituents =
75 spci_memory_region_get_constituents(memory_region);
76
77 for (index = 0; index < constituent_count; index++) {
78 region_constituents[index] = constituents[index];
Andrew Walbran66839252019-11-07 16:01:48 +000079 memory_region->page_count += constituents[index].page_count;
80 }
81
82 /*
83 * TODO: Add assert ensuring that the specified message
84 * length is not greater than SPCI_MSG_PAYLOAD_MAX.
85 */
86
87 return memory_region->constituent_offset + constituents_length;
88}