blob: 4da01fe37fe4355a88dac051ccc6d6556946192f [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(
35 struct spci_memory_region *memory_region, spci_vm_id_t receiver,
36 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 Walbran66839252019-11-07 16:01:48 +000057 memory_region->page_count = 0;
58 memory_region->constituent_count = constituent_count;
59 memory_region->attribute_count = 1;
60 memory_region->attributes[0].receiver = receiver;
61 memory_region->attributes[0].memory_attributes = attributes;
62
63 /*
64 * Constituent offset must be aligned to a 64-bit boundary so that
65 * 64-bit addresses can be copied without alignment faults.
66 */
67 memory_region->constituent_offset = align_up(
68 sizeof(struct spci_memory_region) +
69 memory_region->attribute_count *
70 sizeof(struct spci_memory_region_attributes),
71 8);
72 region_constituents =
73 spci_memory_region_get_constituents(memory_region);
74
75 for (index = 0; index < constituent_count; index++) {
76 region_constituents[index] = constituents[index];
77 region_constituents[index].reserved = 0;
78 memory_region->page_count += constituents[index].page_count;
79 }
80
81 /*
82 * TODO: Add assert ensuring that the specified message
83 * length is not greater than SPCI_MSG_PAYLOAD_MAX.
84 */
85
86 return memory_region->constituent_offset + constituents_length;
87}