memranges: Change align attribute to be log2 of required alignment

This change updates the align attribute of memranges to be represented
as log2 of the required alignment. This makes it consistent with how
alignment is stored in struct resource as well.

Additionally, since memranges only allow power of 2 alignments, this
change allows getting rid of checks at runtime and hence failure cases
for non-power of 2 alignments.

This change also updates the type of align to be unsigned char.

BUG=b:149186922

Signed-off-by: Furquan Shaikh <furquan@google.com>
Change-Id: Ie4d3868cdff55b2c7908b9b3ccd5f30a5288e62f
Reviewed-on: https://review.coreboot.org/c/coreboot/+/39810
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Aaron Durbin <adurbin@chromium.org>
This commit is contained in:
Furquan Shaikh 2020-03-24 14:56:38 -07:00 committed by Patrick Georgi
parent f79f8b4e33
commit 1908340b69
2 changed files with 23 additions and 33 deletions

View File

@ -24,8 +24,8 @@ struct memranges {
/* coreboot doesn't have a free() function. Therefore, keep a cache of /* coreboot doesn't have a free() function. Therefore, keep a cache of
* free'd entries. */ * free'd entries. */
struct range_entry *free_list; struct range_entry *free_list;
/* Alignment for base and end addresses of the range. (Must be power of 2). */ /* Alignment(log 2) for base and end addresses of the range. */
size_t align; unsigned char align;
}; };
/* Each region within a memranges structure is represented by a /* Each region within a memranges structure is represented by a
@ -96,29 +96,29 @@ static inline bool memranges_is_empty(struct memranges *ranges)
/* Initialize memranges structure providing an optional array of range_entry /* Initialize memranges structure providing an optional array of range_entry
* to use as the free list. Additionally, it accepts an align parameter that * to use as the free list. Additionally, it accepts an align parameter that
* determines the alignment of addresses. (Alignment must be a power of 2). */ * represents the required alignment(log 2) of addresses. */
void memranges_init_empty_with_alignment(struct memranges *ranges, void memranges_init_empty_with_alignment(struct memranges *ranges,
struct range_entry *free, struct range_entry *free,
size_t num_free, size_t align); size_t num_free, unsigned char align);
/* Initialize and fill a memranges structure according to the /* Initialize and fill a memranges structure according to the
* mask and match type for all memory resources. Tag each entry with the * mask and match type for all memory resources. Tag each entry with the
* specified type. Additionally, it accepts an align parameter that * specified type. Additionally, it accepts an align parameter that
* determines the alignment of addresses. (Alignment must be a power of 2). */ * represents the required alignment(log 2) of addresses. */
void memranges_init_with_alignment(struct memranges *ranges, void memranges_init_with_alignment(struct memranges *ranges,
unsigned long mask, unsigned long match, unsigned long mask, unsigned long match,
unsigned long tag, size_t align); unsigned long tag, unsigned char align);
/* Initialize memranges structure providing an optional array of range_entry /* Initialize memranges structure providing an optional array of range_entry
* to use as the free list. Addresses are default aligned to 4KiB. */ * to use as the free list. Addresses are default aligned to 4KiB(2^12). */
#define memranges_init_empty(__ranges, __free, __num_free) \ #define memranges_init_empty(__ranges, __free, __num_free) \
memranges_init_empty_with_alignment(__ranges, __free, __num_free, 4 * KiB) memranges_init_empty_with_alignment(__ranges, __free, __num_free, 12);
/* Initialize and fill a memranges structure according to the /* Initialize and fill a memranges structure according to the
* mask and match type for all memory resources. Tag each entry with the * mask and match type for all memory resources. Tag each entry with the
* specified type. Addresses are default aligned to 4KiB. */ * specified type. Addresses are default aligned to 4KiB(2^12). */
#define memranges_init(__ranges, __mask, __match, __tag) \ #define memranges_init(__ranges, __mask, __match, __tag) \
memranges_init_with_alignment(__ranges, __mask, __match, __tag, 4 * KiB) memranges_init_with_alignment(__ranges, __mask, __match, __tag, 12);
/* Clone a memrange. The new memrange has the same entries as the old one. */ /* Clone a memrange. The new memrange has the same entries as the old one. */
void memranges_clone(struct memranges *newranges, struct memranges *oldranges); void memranges_clone(struct memranges *newranges, struct memranges *oldranges);
@ -175,14 +175,13 @@ struct range_entry *memranges_next_entry(struct memranges *ranges,
/* Steals memory from the available list in given ranges as per the constraints: /* Steals memory from the available list in given ranges as per the constraints:
* limit = Upper bound for the memory range to steal. * limit = Upper bound for the memory range to steal.
* size = Requested size for the stolen memory. * size = Requested size for the stolen memory.
* align = Alignment requirements for the starting address of the stolen memory. * align = Required alignment(log 2) for the starting address of the stolen memory.
* (Alignment must be a power of 2).
* tag = Use a range that matches the given tag. * tag = Use a range that matches the given tag.
* *
* If the constraints can be satisfied, this function creates a hole in the memrange, * If the constraints can be satisfied, this function creates a hole in the memrange,
* writes the base address of that hole to stolen_base and returns true. Otherwise it returns * writes the base address of that hole to stolen_base and returns true. Otherwise it returns
* false. */ * false. */
bool memranges_steal(struct memranges *ranges, resource_t limit, resource_t size, size_t align, bool memranges_steal(struct memranges *ranges, resource_t limit, resource_t size,
unsigned long tag, resource_t *stolen_base); unsigned char align, unsigned long tag, resource_t *stolen_base);
#endif /* MEMRANGE_H_ */ #endif /* MEMRANGE_H_ */

View File

@ -230,12 +230,12 @@ static void do_action(struct memranges *ranges,
if (size == 0) if (size == 0)
return; return;
/* The addresses are aligned to 4096 bytes: the begin address is /* The addresses are aligned to (1ULL << ranges->align): the begin address is
* aligned down while the end address is aligned up to be conservative * aligned down while the end address is aligned up to be conservative
* about the full range covered. */ * about the full range covered. */
begin = ALIGN_DOWN(base, ranges->align); begin = ALIGN_DOWN(base, POWER_OF_2(ranges->align));
end = begin + size + (base - begin); end = begin + size + (base - begin);
end = ALIGN_UP(end, ranges->align) - 1; end = ALIGN_UP(end, POWER_OF_2(ranges->align)) - 1;
action(ranges, begin, end, tag); action(ranges, begin, end, tag);
} }
@ -294,13 +294,10 @@ void memranges_add_resources(struct memranges *ranges,
void memranges_init_empty_with_alignment(struct memranges *ranges, void memranges_init_empty_with_alignment(struct memranges *ranges,
struct range_entry *to_free, struct range_entry *to_free,
size_t num_free, size_t align) size_t num_free, unsigned char align)
{ {
size_t i; size_t i;
/* Alignment must be a power of 2. */
assert(IS_POWER_OF_2(align));
ranges->entries = NULL; ranges->entries = NULL;
ranges->free_list = NULL; ranges->free_list = NULL;
ranges->align = align; ranges->align = align;
@ -311,7 +308,7 @@ void memranges_init_empty_with_alignment(struct memranges *ranges,
void memranges_init_with_alignment(struct memranges *ranges, void memranges_init_with_alignment(struct memranges *ranges,
unsigned long mask, unsigned long match, unsigned long mask, unsigned long match,
unsigned long tag, size_t align) unsigned long tag, unsigned char align)
{ {
memranges_init_empty_with_alignment(ranges, NULL, 0, align); memranges_init_empty_with_alignment(ranges, NULL, 0, align);
memranges_add_resources(ranges, mask, match, tag); memranges_add_resources(ranges, mask, match, tag);
@ -395,7 +392,7 @@ struct range_entry *memranges_next_entry(struct memranges *ranges,
* required alignment, is big enough, does not exceed the limit and has a matching tag. */ * required alignment, is big enough, does not exceed the limit and has a matching tag. */
static const struct range_entry *memranges_find_entry(struct memranges *ranges, static const struct range_entry *memranges_find_entry(struct memranges *ranges,
resource_t limit, resource_t size, resource_t limit, resource_t size,
size_t align, unsigned long tag) unsigned char align, unsigned long tag)
{ {
const struct range_entry *r; const struct range_entry *r;
resource_t base, end; resource_t base, end;
@ -403,18 +400,12 @@ static const struct range_entry *memranges_find_entry(struct memranges *ranges,
if (size == 0) if (size == 0)
return NULL; return NULL;
if (!IS_POWER_OF_2(align))
return NULL;
if (!IS_ALIGNED(align, ranges->align))
return NULL;
memranges_each_entry(r, ranges) { memranges_each_entry(r, ranges) {
if (r->tag != tag) if (r->tag != tag)
continue; continue;
base = ALIGN_UP(r->begin, align); base = ALIGN_UP(r->begin, POWER_OF_2(align));
end = base + size - 1; end = base + size - 1;
if (end > r->end) if (end > r->end)
@ -429,8 +420,8 @@ static const struct range_entry *memranges_find_entry(struct memranges *ranges,
return NULL; return NULL;
} }
bool memranges_steal(struct memranges *ranges, resource_t limit, resource_t size, size_t align, bool memranges_steal(struct memranges *ranges, resource_t limit, resource_t size,
unsigned long tag, resource_t *stolen_base) unsigned char align, unsigned long tag, resource_t *stolen_base)
{ {
resource_t base; resource_t base;
const struct range_entry *r = memranges_find_entry(ranges, limit, size, align, tag); const struct range_entry *r = memranges_find_entry(ranges, limit, size, align, tag);
@ -438,7 +429,7 @@ bool memranges_steal(struct memranges *ranges, resource_t limit, resource_t size
if (r == NULL) if (r == NULL)
return false; return false;
base = ALIGN_UP(r->begin, align); base = ALIGN_UP(r->begin, POWER_OF_2(align));
memranges_create_hole(ranges, base, size); memranges_create_hole(ranges, base, size);
*stolen_base = base; *stolen_base = base;