iPXE
memmap.h
Go to the documentation of this file.
1 #ifndef _IPXE_MEMMAP_H
2 #define _IPXE_MEMMAP_H
3 
4 /** @file
5  *
6  * System memory map
7  *
8  */
9 
10 FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
11 
12 #include <stddef.h>
13 #include <stdint.h>
14 #include <ipxe/api.h>
15 #include <ipxe/tables.h>
16 #include <config/ioapi.h>
17 
18 /**
19  * Calculate static inline memory map API function name
20  *
21  * @v _prefix Subsystem prefix
22  * @v _api_func API function
23  * @ret _subsys_func Subsystem API function
24  */
25 #define MEMMAP_INLINE( _subsys, _api_func ) \
26  SINGLE_API_INLINE ( MEMMAP_PREFIX_ ## _subsys, _api_func )
27 
28 /**
29  * Provide a memory map API implementation
30  *
31  * @v _prefix Subsystem prefix
32  * @v _api_func API function
33  * @v _func Implementing function
34  */
35 #define PROVIDE_MEMMAP( _subsys, _api_func, _func ) \
36  PROVIDE_SINGLE_API ( MEMMAP_PREFIX_ ## _subsys, _api_func, _func )
37 
38 /**
39  * Provide a static inline memory map API implementation
40  *
41  * @v _prefix Subsystem prefix
42  * @v _api_func API function
43  */
44 #define PROVIDE_MEMMAP_INLINE( _subsys, _api_func ) \
45  PROVIDE_SINGLE_API_INLINE ( MEMMAP_PREFIX_ ## _subsys, _api_func )
46 
47 /** A memory region descriptor */
48 struct memmap_region {
49  /** Minimum address in region */
51  /** Maximum address in region */
53  /** Region flags */
54  unsigned int flags;
55  /** Region name (for debug messages) */
56  const char *name;
57 };
58 
59 #define MEMMAP_FL_MEMORY 0x0001 /**< Contains memory */
60 #define MEMMAP_FL_RESERVED 0x0002 /**< Is reserved */
61 #define MEMMAP_FL_USED 0x0004 /**< Is in use by iPXE */
62 #define MEMMAP_FL_INACCESSIBLE 0x0008 /**< Outside of addressable range */
63 
64 /**
65  * Initialise memory region descriptor
66  *
67  * @v min Minimum address
68  * @v region Region descriptor to fill in
69  */
70 static inline __attribute__ (( always_inline )) void
71 memmap_init ( uint64_t min, struct memmap_region *region ) {
72 
73  region->min = min;
74  region->max = ~( ( uint64_t ) 0 );
75  region->flags = 0;
76  region->name = NULL;
77 }
78 
79 /**
80  * Check if memory region is usable
81  *
82  * @v region Region descriptor
83  * @ret is_usable Memory region is usable
84  */
85 static inline __attribute__ (( always_inline )) int
86 memmap_is_usable ( const struct memmap_region *region ) {
87 
88  return ( region->flags == MEMMAP_FL_MEMORY );
89 }
90 
91 /**
92  * Get remaining size of memory region (from the described address upwards)
93  *
94  * @v region Region descriptor
95  * @ret size Size of memory region
96  */
97 static inline __attribute__ (( always_inline )) uint64_t
98 memmap_size ( const struct memmap_region *region ) {
99 
100  /* Calculate size, assuming overflow is known to be impossible */
101  return ( region->max - region->min + 1 );
102 }
103 
104 /** An in-use memory region */
105 struct used_region {
106  /** Region name */
107  const char *name;
108  /** Start address */
110  /** Length of region */
111  size_t size;
112 };
113 
114 /** In-use memory region table */
115 #define USED_REGIONS __table ( struct used_region, "used_regions" )
116 
117 /** Declare an in-use memory region */
118 #define __used_region __table_entry ( USED_REGIONS, 01 )
119 
120 /* Include all architecture-independent ACPI API headers */
121 #include <ipxe/null_memmap.h>
122 #include <ipxe/fdtmem.h>
123 
124 /* Include all architecture-dependent ACPI API headers */
125 #include <bits/memmap.h>
126 
127 /**
128  * Describe memory region from system memory map
129  *
130  * @v min Minimum address
131  * @v hide Hide in-use regions from the memory map
132  * @v region Region descriptor to fill in
133  */
134 void memmap_describe ( uint64_t min, int hide, struct memmap_region *region );
135 
136 /**
137  * Synchronise in-use regions with the externally visible system memory map
138  *
139  * In environments such as x86 BIOS, we need to patch the global
140  * system memory map to hide our in-use regions, since there is no
141  * other way to communicate this information to external code.
142  */
143 void memmap_sync ( void );
144 
145 /**
146  * Update an in-use memory region
147  *
148  * @v used In-use memory region
149  * @v start Start address
150  * @v size Length of region
151  */
152 static inline __attribute__ (( always_inline )) void
153 memmap_use ( struct used_region *used, physaddr_t start, size_t size ) {
154 
155  /* Record region */
156  used->start = start;
157  used->size = size;
158 
159  /* Synchronise externally visible memory map */
160  memmap_sync();
161 }
162 
163 /**
164  * Iterate over memory regions from a given starting address
165  *
166  * @v region Region descriptor
167  * @v start Starting address
168  * @v hide Hide in-use regions from the memory map
169  */
170 #define for_each_memmap_from( region, start, hide ) \
171  for ( (region)->min = (start), (region)->max = 0 ; \
172  ( ( ( (region)->max + 1 ) != 0 ) && \
173  ( memmap_describe ( (region)->min, (hide), \
174  (region) ), 1 ) ) ; \
175  (region)->min = ( (region)->max + 1 ) )
176 
177 /**
178  * Iterate over memory regions
179  *
180  * @v region Region descriptor
181  * @v hide Hide in-use regions from the memory map
182  */
183 #define for_each_memmap( region, hide ) \
184  for_each_memmap_from ( (region), 0, (hide) )
185 
186 #define DBG_MEMMAP_IF( level, region ) do { \
187  const char *name = (region)->name; \
188  unsigned int flags = (region)->flags; \
189  \
190  DBG_IF ( level, "MEMMAP (%s%s%s%s) [%#08llx,%#08llx]%s%s\n", \
191  ( ( flags & MEMMAP_FL_MEMORY ) ? "M" : "-" ), \
192  ( ( flags & MEMMAP_FL_RESERVED ) ? "R" : "-" ), \
193  ( ( flags & MEMMAP_FL_USED ) ? "U" : "-" ), \
194  ( ( flags & MEMMAP_FL_INACCESSIBLE ) ? "X" : "-" ), \
195  ( ( unsigned long long ) (region)->min ), \
196  ( ( unsigned long long ) (region)->max ), \
197  ( name ? " " : "" ), ( name ? name : "" ) ); \
198  } while ( 0 )
199 
200 #define DBGC_MEMMAP_IF( level, id, ... ) do { \
201  DBG_AC_IF ( level, id ); \
202  DBG_MEMMAP_IF ( level, __VA_ARGS__ ); \
203  DBG_DC_IF ( level ); \
204  } while ( 0 )
205 
206 #define DBGC_MEMMAP( ... ) DBGC_MEMMAP_IF ( LOG, ##__VA_ARGS__ )
207 #define DBGC2_MEMMAP( ... ) DBGC_MEMMAP_IF ( EXTRA, ##__VA_ARGS__ )
208 #define DBGCP_MEMMAP( ... ) DBGC_MEMMAP_IF ( PROFILE, ##__VA_ARGS__ )
209 
210 /**
211  * Dump system memory map (for debugging)
212  *
213  * @v hide Hide in-use regions from the memory map
214  */
215 static inline void memmap_dump_all ( int hide ) {
216  struct memmap_region region;
217 
218  /* Do nothing unless debugging is enabled */
219  if ( ! DBG_LOG )
220  return;
221 
222  /* Describe all memory regions */
223  DBGC ( &memmap_describe, "MEMMAP with in-use regions %s:\n",
224  ( hide ? "hidden" : "ignored" ) );
225  for_each_memmap ( &region, hide )
226  DBGC_MEMMAP ( &memmap_describe, &region );
227 }
228 
229 extern void memmap_update ( struct memmap_region *region, uint64_t start,
230  uint64_t size, unsigned int flags,
231  const char *name );
232 extern void memmap_update_used ( struct memmap_region *region );
233 extern size_t memmap_largest ( physaddr_t *start );
234 
235 #endif /* _IPXE_MEMMAP_H */
static int memmap_is_usable(const struct memmap_region *region)
Check if memory region is usable.
Definition: memmap.h:86
#define __attribute__(x)
Definition: compiler.h:10
size_t size
Length of region.
Definition: memmap.h:111
static void memmap_use(struct used_region *used, physaddr_t start, size_t size)
Update an in-use memory region.
Definition: memmap.h:153
const char * name
Definition: ath9k_hw.c:1984
iPXE internal APIs
uint64_t max
Maximum address in region.
Definition: memmap.h:52
uint16_t size
Buffer size.
Definition: dwmac.h:14
Flattened Device Tree memory map.
#define DBGC(...)
Definition: compiler.h:505
#define min(x, y)
Definition: ath.h:35
unsigned long long uint64_t
Definition: stdint.h:13
size_t memmap_largest(physaddr_t *start)
Find largest usable memory region.
Definition: memmap.c:120
void memmap_update_used(struct memmap_region *region)
Update memory region descriptor based on all in-use memory regions.
Definition: memmap.c:104
#define DBGC_MEMMAP(...)
Definition: memmap.h:206
uint32_t start
Starting offset.
Definition: netvsc.h:12
physaddr_t start
Start address.
Definition: memmap.h:109
void memmap_describe(uint64_t min, int hide, struct memmap_region *region)
Describe memory region from system memory map.
Definition: null_memmap.h:28
#define for_each_memmap(region, hide)
Iterate over memory regions.
Definition: memmap.h:183
uint8_t flags
Flags.
Definition: ena.h:18
An in-use memory region.
Definition: memmap.h:105
unsigned int flags
Region flags.
Definition: memmap.h:54
const char * name
Region name (for debug messages)
Definition: memmap.h:56
unsigned long physaddr_t
Definition: stdint.h:20
I/O API configuration.
static void memmap_dump_all(int hide)
Dump system memory map (for debugging)
Definition: memmap.h:215
static uint64_t memmap_size(const struct memmap_region *region)
Get remaining size of memory region (from the described address upwards)
Definition: memmap.h:98
#define MEMMAP_FL_MEMORY
Contains memory.
Definition: memmap.h:59
void memmap_update(struct memmap_region *region, uint64_t start, uint64_t size, unsigned int flags, const char *name)
Update memory region descriptor.
Definition: memmap.c:47
const char * name
Region name.
Definition: memmap.h:107
Linker tables.
uint64_t min
Minimum address in region.
Definition: memmap.h:50
Null system memory map API.
A memory region descriptor.
Definition: memmap.h:48
static void memmap_init(uint64_t min, struct memmap_region *region)
Initialise memory region descriptor.
Definition: memmap.h:71
FILE_LICENCE(GPL2_OR_LATER_OR_UBDL)
#define DBG_LOG
Definition: compiler.h:317
#define NULL
NULL pointer (VOID *)
Definition: Base.h:321
void memmap_sync(void)
Synchronise in-use regions with the externally visible system memory map.
Definition: fdtmem.h:25