Software APIs
memory.h
Go to the documentation of this file.
1 // Copyright lowRISC contributors.
2 // Licensed under the Apache License, Version 2.0, see LICENSE for details.
3 // SPDX-License-Identifier: Apache-2.0
4 
5 #ifndef OPENTITAN_SW_DEVICE_LIB_BASE_MEMORY_H_
6 #define OPENTITAN_SW_DEVICE_LIB_BASE_MEMORY_H_
7 
8 /**
9  * @file
10  * @brief OpenTitan Device Memory Library
11  *
12  * This library provides memory functions for aligned word accesses, and some
13  * useful functions from the C library's <string.h>.
14  */
15 
16 #include <stdalign.h>
17 #include <stddef.h>
18 #include <stdint.h>
19 
20 #ifdef __cplusplus
21 extern "C" {
22 #endif // __cplusplus
23 
24 /**
25  * Load a word from memory directly, bypassing aliasing rules.
26  *
27  * ISO C forbids, in general, casting a pointer to non-character types and
28  * reading them, though it is frequently necessary to read exactly one word out
29  * of a `void *`. This function performs that action in a manner which is
30  * well-defined.
31  *
32  * Of course, `ptr` must point to word-aligned memory that is at least one word
33  * wide. To do otherwise is Undefined Behavior. It goes eithout saying that the
34  * memory this function intents to read must be initialized.
35  *
36  * This function has reordering properties as weak as a normal, non-atomic,
37  * non-volatile load.
38  *
39  * @param ptr a word-aligned pointer pointed to at least four bytes of memory.
40  * @return the word `ptr` points to.
41  */
42 inline uint32_t read_32(const void *ptr) {
43  // Both GCC and Clang optimize the code below into a single word-load on most
44  // platforms. It is necessary and sufficient to indicate to the compiler that
45  // the pointer points to four bytes of four-byte-aligned memory.
46  //
47  // Failing to get that particular codegen in either GCC or Clang with -O2 or
48  // -Os set shall be considred a bug in this function. The same applies to
49  // `write32()`.
50  ptr = __builtin_assume_aligned(ptr, alignof(uint32_t));
51  uint32_t val;
52  __builtin_memcpy(&val, ptr, sizeof(uint32_t));
53  return val;
54 }
55 
56 /**
57  * Store a word to memory directly, bypassing aliasing rules.
58  *
59  * ISO C forbids, in general, casting a pointer to non-character types and
60  * reading them, though it is frequently necessary to write exactly one word to
61  * a `void *`. This function performs that action in a manner which is
62  * well-defined.
63  *
64  * Of course, `ptr` must point to word-aligned memory that is at least one word
65  * wide. To do otherwise is Undefined Behavior.
66  *
67  * This function has reordering properties as weak as a normal, non-atomic,
68  * non-volatile load.
69  *
70  * @param value the value to store.
71  * @param ptr a word-aligned pointer pointed to at least four bytes of memory.
72  */
73 inline void write_32(uint32_t value, void *ptr) {
74  // Both GCC and Clang optimize the code below into a single word-store on most
75  // platforms. See the comment in `read_32()` for more implementation-private
76  // information.
77  ptr = __builtin_assume_aligned(ptr, alignof(uint32_t));
78  __builtin_memcpy(ptr, &value, sizeof(uint32_t));
79 }
80 
81 /**
82  * Copy memory between non-overlapping regions.
83  *
84  * This function conforms to the semantics defined in ISO C11 S7.23.2.1.
85  *
86  * This function will be provided by the platform's libc implementation for host
87  * builds.
88  *
89  * @param dest the region to copy to.
90  * @param src the region to copy from.
91  * @param len the number of bytes to copy.
92  * @return the value of `dest`.
93  */
94 void *memcpy(void *restrict dest, const void *restrict src, size_t len);
95 
96 /**
97  * Set a region of memory to a particular byte value.
98  *
99  * This function conforms to the semantics defined in ISO C11 S7.23.6.1.
100  *
101  * This function will be provided by the platform's libc implementation for host
102  * builds.
103  *
104  * @param dest the region to write to.
105  * @param value the value, converted to a byte, to write to each byte cell.
106  * @param len the number of bytes to write.
107  * @return the value of `dest`.
108  */
109 void *memset(void *dest, int value, size_t len);
110 
111 /**
112  * Compare two (potentially overlapping) regions of memory for byte-wise
113  * lexicographic order.
114  *
115  * This function conforms to the semantics defined in ISO C11 S7.24.4.1.
116  *
117  * This function will be provided by the platform's libc implementation for host
118  * builds.
119  *
120  * @param lhs the left-hand-side of the comparison.
121  * @param rhs the right-hand-side of the comparison.
122  * @param len the length of both regions, in bytes.
123  * @return a zero, positive, or negative integer, corresponding to the
124  * contingencies of `lhs == rhs`, `lhs > rhs`, and `lhs < rhs` (as buffers, not
125  * pointers), respectively.
126  */
127 int memcmp(const void *lhs, const void *rhs, size_t len);
128 
129 /**
130  * Search a region of memory for the first occurence of a particular byte value.
131  *
132  * This function conforms to the semantics defined in ISO C11 S7.24.5.1.
133  *
134  * Since libbase does not provide a `strlen()` function, this function can be
135  * used as an approximation: `memchr(my_str, 0, SIZE_MAX) - my_str`.
136  *
137  * This function will be provided by the platform's libc implementation for host
138  * builds.
139  *
140  * @param ptr the region to search.
141  * @param value the value, converted to a byte, to search for.
142  * @param len the length of the region, in bytes.
143  * @return a pointer to the found value, or NULL.
144  */
145 void *memchr(const void *ptr, int value, size_t len);
146 
147 /**
148  * Search a region of memory for the last occurence of a particular byte value.
149  *
150  * This function is not specified by C11, but is named for a well-known glibc
151  * extension.
152  *
153  * @param ptr the region to search.
154  * @param value the value, converted to a byte, to search for.
155  * @param len the length of the region, in bytes.
156  * @return a pointer to the found value, or NULL.
157  */
158 void *memrchr(const void *ptr, int value, size_t len);
159 
160 #ifdef __cplusplus
161 } // extern "C"
162 #endif // __cplusplus
163 
164 #endif // OPENTITAN_SW_DEVICE_LIB_BASE_MEMORY_H_