summaryrefslogtreecommitdiffstats
path: root/src/include/imd.h
blob: df669fd3669ffdf8abece992087900e298cd9f2f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
/* SPDX-License-Identifier: GPL-2.0-only */

#ifndef _IMD_H_
#define _IMD_H_

#include <stdint.h>
#include <stddef.h>

/*
 * imd is an in-memory database/directory/datastore (whatever d word you
 * desire). It grows downwards in memory from provided upper limit and
 * root size. Each entry has a size alignment which is also provided by
 * the caller.
 *
 *             +----------------------+ <- upper_limit
 *    |   +----|   root pointer       |
 *    |   |    +----------------------+
 *    |   |    |                      |--------+
 *    |   +--->|   root block         |-----+  |
 *    |        +----------------------+-----|--|--- root_size
 *    |        |                      |     |  |
 *    |        |                      |     |  |
 *    |        |   alloc N            |<----+  |
 *    |        +----------------------+        |
 *    |        |                      |        |
 *    |        |                      |        |
 *   \|/       |   alloc N + 1        |<-------+
 *    v        +----------------------+
 *
 * The root_size in imd_create_empty() encompasses the root pointer
 * and root block. The root_size value, therefore, dictates the number
 * of allocations maintained by the imd.
 */

/*
 * NOTE: This API has the following calling conventions: all functions
 * returning int supply 0 on success or < 0 on error.
 */

struct imd_entry;
struct imd;

static const size_t LIMIT_ALIGN = 4096;

/*
 * Initialize handle to use for working with an imd. Upper limit is the
 * exclusive address (aligned down to LIMIT_ALIGN) to start allocating down
 * from. This function needs to be called at least once before any other imd
 * related functions can be used.
 */
void imd_handle_init(struct imd *imd, void *upper_limit);

/*
 * Initialize a handle with a shallow recovery. This function doesn't
 * verify every entry, but it does set up the root pointer. Because of
 * this behavior it's not very safe. However, the current CBMEM constraints
 * demand having these semantics.
 */
void imd_handle_init_partial_recovery(struct imd *imd);

/*
 * Create an empty imd with a specified root_size and each entry is aligned to
 * the provided entry_align. As noted above the root size encompasses the
 * root pointer and root block leading to the number of imd entries being a
 * function of the root_size parameter. Please note, that one entry is allocated
 * for covering root region, thus caller should consider this calculating
 * root_size.
 */
int imd_create_empty(struct imd *imd, size_t root_size, size_t entry_align);

/*
 * Create an empty imd with both large and small allocations. The small
 * allocations come from a fixed imd stored internally within the large
 * imd. The region allocated for tracking the smaller allocations is dependent
 * on the small root_size and the large entry alignment by calculating the
 * number of entries within the small imd and multiplying that by the small
 * entry alignment.
 */
int imd_create_tiered_empty(struct imd *imd,
				size_t lg_root_size, size_t lg_entry_align,
				size_t sm_root_size, size_t sm_entry_align);

/*
 * Recover a previously created imd.
 */
int imd_recover(struct imd *imd);

/* Limit imd to provided max_size. */
int imd_limit_size(struct imd *imd, size_t max_size);

/* Lock down imd from further modifications. */
int imd_lockdown(struct imd *imd);

/* Fill in base address and size of region used by imd. */
int imd_region_used(struct imd *imd, void **base, size_t *size);

/* Add an entry to the imd. If id already exists NULL is returned. */
const struct imd_entry *imd_entry_add(const struct imd *imd, uint32_t id,
					size_t size);

/* Locate an entry within the imd. NULL is returned when not found. */
const struct imd_entry *imd_entry_find(const struct imd *imd, uint32_t id);

/* Find an existing entry or add a new one. */
const struct imd_entry *imd_entry_find_or_add(const struct imd *imd,
						uint32_t id, size_t size);

/* Returns size of entry. */
size_t imd_entry_size(const struct imd_entry *entry);

/* Returns pointer to region described by entry or NULL on failure. */
void *imd_entry_at(const struct imd *imd, const struct imd_entry *entry);

/* Returns id for the imd entry. */
uint32_t imd_entry_id(const struct imd_entry *entry);

/* Attempt to remove entry from imd. */
int imd_entry_remove(const struct imd *imd, const struct imd_entry *entry);

/* Print the entry information provided by lookup with the specified size. */
struct imd_lookup {
	uint32_t id;
	const char *name;
};

int imd_print_entries(const struct imd *imd, const struct imd_lookup *lookup,
			size_t size);

struct imd_cursor;
/* Initialize an imd_cursor object to walk the IMD entries. */
int imd_cursor_init(const struct imd *imd, struct imd_cursor *cursor);

/* Retrieve the next imd entry the cursor is referencing. Returns NULL when
 * no more entries exist. */
const struct imd_entry *imd_cursor_next(struct imd_cursor *cursor);

/*
 * The struct imd is a handle for working with an in-memory directory.
 *
 * NOTE: Do not directly touch any fields within this structure. An imd pointer
 * is meant to be opaque, but the fields are exposed for stack allocation.
 */
struct imdr {
	uintptr_t limit;
	void *r;
};
struct imd {
	struct imdr lg;
	struct imdr sm;
};

struct imd_cursor {
	size_t current_imdr;
	size_t current_entry;
	const struct imdr *imdr[2];
};

#endif /* _IMD_H_ */