blob: 45d7b371d04524cb788ab11a65da00879e858c19 [file] [log] [blame]
Andrew Scull18834872018-10-12 11:48:09 +01001/*
Andrew Walbran692b3252019-03-07 15:51:31 +00002 * Copyright 2018 The Hafnium Authors.
Andrew Scull18834872018-10-12 11:48:09 +01003 *
Andrew Walbrane959ec12020-06-17 15:01:09 +01004 * Use of this source code is governed by a BSD-style
5 * license that can be found in the LICENSE file or at
6 * https://opensource.org/licenses/BSD-3-Clause.
Andrew Scull18834872018-10-12 11:48:09 +01007 */
8
Andrew Scullfbc938a2018-08-20 14:09:28 +01009#pragma once
Andrew Scull8dce4982018-08-06 13:02:20 +010010
11#include <stddef.h>
12#include <stdint.h>
13
Andrew Scull11a4a0c2018-12-29 11:38:31 +000014#include "hf/arch/types.h"
Andrew Scull8dce4982018-08-06 13:02:20 +010015
Daniel Boulby84350712021-11-26 11:13:20 +000016#include "hf/assert.h"
Fuad Tabba50469e02020-06-30 15:14:28 +010017
Andrew Walbranc3910f72018-11-27 14:24:36 +000018/** An opaque type for a physical address. */
Andrew Scull8dce4982018-08-06 13:02:20 +010019typedef struct {
20 uintpaddr_t pa;
21} paddr_t;
22
Andrew Walbranc3910f72018-11-27 14:24:36 +000023/** An opaque type for an intermediate physical address. */
Andrew Scull8dce4982018-08-06 13:02:20 +010024typedef struct {
25 uintpaddr_t ipa;
26} ipaddr_t;
27
Andrew Walbranc3910f72018-11-27 14:24:36 +000028/** An opaque type for a virtual address. */
Andrew Scull8dce4982018-08-06 13:02:20 +010029typedef struct {
30 uintvaddr_t va;
31} vaddr_t;
32
33/**
34 * Initializes a physical address.
35 */
36static inline paddr_t pa_init(uintpaddr_t p)
37{
38 return (paddr_t){.pa = p};
39}
40
41/**
42 * Extracts the absolute physical address.
43 */
44static inline uintpaddr_t pa_addr(paddr_t pa)
45{
46 return pa.pa;
47}
48
49/**
Andrew Scull81e85092018-12-12 12:56:20 +000050 * Advances a physical address.
51 */
52static inline paddr_t pa_add(paddr_t pa, size_t n)
53{
54 return pa_init(pa_addr(pa) + n);
55}
56
57/**
Manish Pandey2145c212020-05-01 16:04:22 +010058 * Move backward physical address.
59 */
60static inline paddr_t pa_subtract(paddr_t pa, size_t n)
61{
62 return pa_init(pa_addr(pa) - n);
63}
64
65/**
Andrew Walbran2cb43392019-04-17 12:52:45 +010066 * Returns the difference between two physical addresses.
67 */
68static inline size_t pa_difference(paddr_t start, paddr_t end)
69{
70 return pa_addr(end) - pa_addr(start);
71}
72
73/**
Max Shvetsov9c0ebe42020-08-27 12:37:57 +010074 * Initializes an intermediate physical address.
Andrew Scull8dce4982018-08-06 13:02:20 +010075 */
Alfredo Mazzinghi8cc983e2019-02-22 15:12:36 +000076static inline ipaddr_t ipa_init(uintpaddr_t ipa)
Andrew Scull8dce4982018-08-06 13:02:20 +010077{
Alfredo Mazzinghi8cc983e2019-02-22 15:12:36 +000078 return (ipaddr_t){.ipa = ipa};
Andrew Scull8dce4982018-08-06 13:02:20 +010079}
80
81/**
Fuad Tabba50469e02020-06-30 15:14:28 +010082 * Subtract from a physical address.
83 */
84static inline paddr_t pa_sub(paddr_t pa, size_t n)
85{
Daniel Boulby84350712021-11-26 11:13:20 +000086 assert((uintptr_t)pa_addr(pa) >= n);
Fuad Tabba50469e02020-06-30 15:14:28 +010087 return pa_init(pa_addr(pa) - n);
88}
89
90/**
Andrew Scull8dce4982018-08-06 13:02:20 +010091 * Extracts the absolute intermediate physical address.
92 */
93static inline uintpaddr_t ipa_addr(ipaddr_t ipa)
94{
95 return ipa.ipa;
96}
97
98/**
Andrew Scull81e85092018-12-12 12:56:20 +000099 * Advances an intermediate physical address.
100 */
101static inline ipaddr_t ipa_add(ipaddr_t ipa, size_t n)
102{
103 return ipa_init(ipa_addr(ipa) + n);
104}
105
106/**
Andrew Scull8dce4982018-08-06 13:02:20 +0100107 * Initializes a virtual address.
108 */
109static inline vaddr_t va_init(uintvaddr_t v)
110{
111 return (vaddr_t){.va = v};
112}
113
114/**
115 * Extracts the absolute virtual address.
116 */
117static inline uintvaddr_t va_addr(vaddr_t va)
118{
119 return va.va;
120}
121
122/**
Andrew Scull8dce4982018-08-06 13:02:20 +0100123 * Casts a physical address to a virtual address.
124 */
125static inline vaddr_t va_from_pa(paddr_t pa)
126{
127 return va_init(pa_addr(pa));
128}
129
130/**
Andrew Scull1b8d0442018-08-06 15:47:04 +0100131 * Casts a physical address to an intermediate physical address.
132 */
133static inline ipaddr_t ipa_from_pa(paddr_t pa)
134{
135 return ipa_init(pa_addr(pa));
136}
137
138/**
Andrew Scull8dce4982018-08-06 13:02:20 +0100139 * Casts a virtual address to a physical address.
140 */
141static inline paddr_t pa_from_va(vaddr_t va)
142{
143 return pa_init(va_addr(va));
144}
145
146/**
Andrew Scullc2eb6a32018-12-13 16:54:24 +0000147 * Casts an intermediate physical address to a physical address.
148 */
149static inline paddr_t pa_from_ipa(ipaddr_t ipa)
150{
151 return pa_init(ipa_addr(ipa));
152}
153
154/**
Andrew Scull8dce4982018-08-06 13:02:20 +0100155 * Casts a pointer to a virtual address.
156 */
157static inline vaddr_t va_from_ptr(const void *p)
158{
159 return (vaddr_t){.va = (uintvaddr_t)p};
160}
161
162/**
163 * Casts a virtual address to a pointer. Only use when the virtual address is
164 * mapped for the calling context.
165 * TODO: check the mapping for a range and return a memiter?
166 */
167static inline void *ptr_from_va(vaddr_t va)
168{
169 return (void *)va_addr(va);
170}
Raghu Krishnamurthyea6d25f2021-09-14 15:27:06 -0700171
172/**
173 * Advances a virtual address.
174 */
175static inline vaddr_t va_add(vaddr_t va, size_t n)
176{
177 return va_init(va_addr(va) + n);
178}